1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.services.registry;
18
19
20 import java.io.Reader;
21 import java.util.Hashtable;
22 import java.util.Enumeration;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Vector;
27
28 import javax.servlet.ServletConfig;
29
30
31 import org.apache.turbine.services.InitializationException;
32 import org.apache.turbine.services.TurbineBaseService;
33 import org.apache.turbine.services.TurbineServices;
34 import org.apache.turbine.services.resources.ResourceService;
35 import org.apache.turbine.services.servlet.ServletService;
36
37
38 import org.apache.jetspeed.om.registry.DBRegistry;
39 import org.apache.jetspeed.om.registry.Registry;
40 import org.apache.jetspeed.om.registry.RegistryEntry;
41 import org.apache.jetspeed.om.registry.RegistryException;
42 import org.apache.jetspeed.om.registry.base.BaseRegistry;
43 import org.apache.jetspeed.om.registry.base.LocalRegistry;
44 import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
45 import org.apache.jetspeed.services.logging.JetspeedLogger;
46
47 /***
48 * <p>This is an implementation of the <code>RegistryService</code>
49 * based on the Jetspeed Database Persistence Manager</p>
50 *
51 * @author <a href="mailto:taylor@apache.org">David Sean Taylor</a>
52 * @author <a href="mailto:susinha@cisco.com">Suchisubhra Sinha</a>
53 * @version $Id: DatabaseRegistryService.java,v 1.6 2004/02/23 03:31:50 jford Exp $
54 */
55 public class DatabaseRegistryService
56 extends TurbineBaseService
57 implements RegistryService , FileRegistry
58 {
59 private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(CastorRegistryService.class.getName());
60
61 /*** The name of this service */
62 public static String SERVICE_NAME = "DatabaseRegistry";
63
64 public static final int DEFAULT_VERBOSE = 1;
65
66 /*** regsitry type keyed list of entries */
67 private Hashtable registries = new Hashtable();
68
69 /*** The list of default fragments stores for newly created objects */
70 private Hashtable defaults = new Hashtable();
71
72 /*** The Castor generated RegsitryFragment objects */
73 private Hashtable fragments = new Hashtable();
74
75 /*** Associates entries with their fragments name for quick lookup */
76 private Hashtable entryIndex = new Hashtable();
77
78 /*** the Watcher object which monitors the regsitry directory */
79 private DatabaseRegistryWatcher watcher = null;
80
81 /*** Assign the default poolname */
82 private final static String POOL_NAME = "database";
83
84
85 /*** controls amount of debug output, the bigger the more output will be generated */
86 private int verbose = DEFAULT_VERBOSE;
87
88 /*** Base class to implement */
89 private static Hashtable baseClass = new Hashtable();
90
91 /***
92 * Returns a Registry object for further manipulation
93 *
94 * @param regName the name of the registry to fetch
95 * @return a Registry object if found by the manager or null
96 */
97 public Registry get(String regName)
98 {
99 return (Registry) registries.get(regName);
100 }
101
102 /***
103 * List all the registry currently available to this service
104 *
105 * @return an Enumeration of registry names.
106 */
107 public Enumeration getNames()
108 {
109 return registries.keys();
110 }
111
112 /***
113 * Creates a new RegistryEntry instance compatible with the current
114 * Registry instance implementation
115 *
116 * @param regName the name of the registry to use
117 * @return the newly created RegistryEntry
118 */
119 public RegistryEntry createEntry(String regName)
120 {
121 RegistryEntry entry = null;
122 Registry registry = (Registry) registries.get(regName);
123
124 if (registry != null)
125 {
126 entry = registry.createEntry();
127 }
128
129 return entry;
130 }
131
132
133 /***
134 * Returns a RegistryEntry from the named Registry.
135 * This is a convenience wrapper around {@link
136 * org.apache.jetspeed.om.registry.Registry#getEntry }
137 *
138 * @param regName the name of the registry
139 * @param entryName the name of the entry to retrieve from the registry.
140 * @return a RegistryEntry object if the key is found or null
141 */
142 public RegistryEntry getEntry(String regName, String entryName)
143 {
144 try
145 {
146 return ((Registry) registries.get(regName)).getEntry(entryName);
147 }
148 catch (RegistryException e)
149 {
150 if (logger.isInfoEnabled())
151 {
152 logger.info(
153 "RegistryService: Failed to retrieve "
154 + entryName
155 + " from "
156 + regName);
157 }
158 }
159 catch (NullPointerException e)
160 {
161 logger.error(
162 "DatabaseRegistryService: "
163 + regName
164 + " registry is not known ");
165 logger.error(e);
166 }
167
168 return null;
169 }
170
171 /***
172 * Add a new RegistryEntry in the named Registry.
173 * This is a convenience wrapper around {@link
174 * org.apache.jetspeed.om.registry.Registry#addEntry }
175 *
176 * @param regName the name of the registry
177 * @param entry the Registry entry to add
178 * @exception Sends a RegistryException if the manager can't add
179 * the provided entry
180 */
181 public void addEntry(String regName, RegistryEntry entry)
182 throws RegistryException
183 {
184 if (entry == null)
185 {
186 return;
187 }
188
189 LocalRegistry registry = (LocalRegistry) registries.get(regName);
190
191 if (registry != null)
192 {
193 String fragmentName = (String) entryIndex.get(entry.getName());
194
195 if (fragmentName == null)
196 {
197
198
199 fragmentName = (String) defaults.get(regName);
200 }
201
202 RegistryFragment fragment =
203 (RegistryFragment) fragments.get(fragmentName);
204
205
206 if (fragment == null)
207 {
208 fragment = new RegistryFragment();
209 fragment.put(regName, new Vector());
210 fragments.put(fragmentName, fragment);
211 }
212 else
213 {
214 Vector vectRegistry = (Vector) fragment.get(regName);
215 if (vectRegistry == null)
216 {
217 fragment.put(regName, new Vector());
218 }
219 }
220
221 synchronized (entryIndex)
222 {
223 if (registry.hasEntry(entry.getName()))
224 {
225 fragment.setEntry(regName, entry);
226 registry.setLocalEntry(entry);
227 }
228 else
229 {
230 fragment.addEntry(regName, entry);
231 registry.addLocalEntry(entry);
232 }
233
234 entryIndex.put(entry.getName(), fragmentName);
235
236
237 fragment.setDirty(true);
238 }
239 }
240 }
241
242 /***
243 * Deletes a RegistryEntry from the named Registry
244 * This is a convenience wrapper around {@link
245 * org.apache.jetspeed.om.registry.Registry#removeEntry }
246 *
247 * @param regName the name of the registry
248 * @param entryName the name of the entry to remove
249 */
250 public void removeEntry(String regName, String entryName)
251 {
252 if (entryName == null)
253 {
254 return;
255 }
256
257 LocalRegistry registry = (LocalRegistry) registries.get(regName);
258
259 if (registry != null)
260 {
261 String fragmentName = (String) entryIndex.get(entryName);
262
263 if (fragmentName != null)
264 {
265 RegistryFragment fragment =
266 (RegistryFragment) fragments.get(fragmentName);
267
268 synchronized (entryIndex)
269 {
270 fragment.removeEntry(regName, entryName);
271 entryIndex.remove(entryName);
272
273
274
275 fragment.setDirty(true);
276 }
277 }
278
279
280 registry.removeLocalEntry(entryName);
281 }
282 }
283
284 /***
285 * This is the early initialization method called by the
286 * Turbine <code>Service</code> framework
287 */
288 public synchronized void init(ServletConfig conf)
289 throws InitializationException
290 {
291 int refreshRate = 0;
292 Vector names = new Vector();
293
294
295 TurbineServices.getInstance().initService(ServletService.SERVICE_NAME, conf);
296
297 ResourceService serviceConf =
298 ((TurbineServices) TurbineServices.getInstance()).getResources(SERVICE_NAME);
299
300
301
302 try
303 {
304 refreshRate = serviceConf.getInt("refreshRate", DEFAULT_REFRESH);
305 ResourceService defaults = serviceConf.getResources("default");
306 Iterator i = defaults.getKeys();
307
308 while (i.hasNext())
309 {
310 String name = (String) i.next();
311
312
313 names.add(name);
314 try
315 {
316 String registryClass =
317 "org.apache.jetspeed.om.registry.database.BaseJetspeed"
318 + name
319 + "Peer";
320
321 baseClass.put(
322 name,
323 (DBRegistry) Class
324 .forName(registryClass)
325 .newInstance());
326 }
327 catch (Exception e)
328 {
329 if (logger.isWarnEnabled())
330 {
331 logger.warn(
332 "DatabaseRegistryService: Class "
333 + name
334 + " not found");
335 }
336
337 }
338
339 }
340 }
341 catch (Throwable t)
342 {
343 throw new InitializationException("Unable to initialize DatabaseRegistryService, missing config keys");
344 }
345
346 this.watcher = new DatabaseRegistryWatcher();
347 this.watcher.setSubscriber(this);
348
349 if (refreshRate == 0)
350 {
351 this.watcher.setDone();
352 }
353 else
354 {
355 this.watcher.setRefreshRate(refreshRate);
356 }
357
358 this.watcher.changeBase(names);
359
360
361 setInit(true);
362
363
364 Enumeration en = names.elements();
365
366 RegistryService localeService =
367 (RegistryService) TurbineServices
368 .getInstance()
369 .getService(RegistryService.SERVICE_NAME);
370
371 while (en.hasMoreElements())
372 {
373 String name = (String) en.nextElement();
374 Registry registry = (Registry) registries.get(name);
375
376 if (registry == null)
377 {
378 String registryClass = null;
379 try
380 {
381 registry = localeService.get(name);
382 }
383 catch (Exception e)
384 {
385 if (logger.isWarnEnabled())
386 {
387 logger.warn(
388 "DatabaseRegistryService: Class "
389 + registryClass
390 + " not found, reverting to default Registry");
391 }
392 registry = new BaseRegistry();
393 }
394 registries.put(name, registry);
395 }
396
397 refresh(name);
398 }
399
400
401
402 if (this.watcher != null)
403 {
404 this.watcher.start();
405 }
406
407 if (logger.isDebugEnabled())
408 {
409 logger.debug(
410 "DatabaseRegistryService: early init()....end!, this.getInit()= "
411 + getInit());
412 }
413 }
414 /***
415 * @return a Map of all fragments keyed by file names
416 */
417 public Map getFragmentMap()
418 {
419 return (Map) fragments.clone();
420 }
421
422 /*** Late init method from Turbine Service model */
423 public void init() throws InitializationException
424 {
425 if (logger.isDebugEnabled())
426 {
427 logger.debug("DatabaseRegistryService: Late init called");
428 }
429 while (!getInit())
430 {
431
432 try
433 {
434 Thread.sleep(500);
435 if ((verbose > 2) && logger.isDebugEnabled())
436 {
437 logger.debug(
438 "DatabaseRegistryService: Waiting for init of Registry...");
439 }
440 }
441 catch (InterruptedException ie)
442 {
443 logger.error(ie);
444 }
445 }
446
447 if (logger.isDebugEnabled())
448 {
449 logger.debug("DatabaseRegistryService: We are done");
450 }
451 }
452
453 /***
454 * This is the shutdown method called by the
455 * Turbine <code>Service</code> framework
456 */
457 public void shutdown()
458 {
459 this.watcher.setDone();
460
461 Iterator i = fragments.keySet().iterator();
462 while (i.hasNext())
463 {
464 saveFragment((String) i.next());
465 }
466 }
467
468 /***
469 * Scan all the registry fragments for new entries relevant to
470 * this registry and update its definition.
471 *
472 * @param regName the name of the Registry to refresh
473 */
474 protected void refresh(String regName)
475 {
476 if (logger.isDebugEnabled())
477 {
478 logger.debug(
479 "DatabaseRegistryService: Updating the "
480 + regName
481 + " registry");
482 }
483
484 int count = 0;
485 int counDeleted = 0;
486 LocalRegistry registry = (LocalRegistry) get(regName);
487
488 Vector toDelete = new Vector();
489 Iterator i = registry.listEntryNames();
490
491 while (i.hasNext())
492 {
493 toDelete.add(i.next());
494 }
495
496 if (registry == null)
497 {
498 logger.error(
499 "DatabaseRegistryService: Null "
500 + name
501 + " registry in refresh");
502 return;
503 }
504
505
506 Enumeration en = fragments.keys();
507 while (en.hasMoreElements())
508 {
509 String location = (String) en.nextElement();
510 RegistryFragment fragment =
511 (RegistryFragment) fragments.get(location);
512 int fragCount = 0;
513
514 if (!fragment.hasChanged())
515 {
516 if ((verbose > 2) && logger.isDebugEnabled())
517 {
518 logger.debug(
519 "DatabaseRegistryService: Skipping fragment "
520 + location);
521 }
522
523
524 Vector entries = fragment.getEntries(regName);
525 i = entries.iterator();
526 while (i.hasNext())
527 {
528 toDelete.remove(((RegistryEntry) i.next()).getName());
529 }
530 continue;
531 }
532
533
534 Vector entries = fragment.getEntries(regName);
535
536 if (entries != null)
537 {
538
539 Enumeration en2 = entries.elements();
540 while (en2.hasMoreElements())
541 {
542 RegistryEntry entry = (RegistryEntry) en2.nextElement();
543
544 try
545 {
546 if (registry.hasEntry(entry.getName()))
547 {
548 if (registry
549 .getEntry(entry.getName())
550 .equals(entry))
551 {
552 if ((verbose > 2)
553 && logger.isDebugEnabled())
554 {
555 logger.debug(
556 "DatabaseRegistryService: No changes to entry "
557 + entry.getName());
558 }
559 }
560 else
561 {
562 if ((verbose > 1)
563 && logger.isDebugEnabled())
564 {
565 logger.debug(
566 "DatabaseRegistryService: Updating entry "
567 + entry.getName()
568 + " of class "
569 + entry.getClass()
570 + " to registry "
571 + name);
572 }
573 registry.setLocalEntry(entry);
574
575 this.entryIndex.put(entry.getName(), location);
576 ++fragCount;
577 }
578 }
579 else
580 {
581 registry.addLocalEntry(entry);
582
583 this.entryIndex.put(entry.getName(), location);
584 ++fragCount;
585
586 if ((verbose > 1)
587 && logger.isDebugEnabled())
588 {
589 logger.debug(
590 "DatabaseRegistryService: Adding entry "
591 + entry.getName()
592 + " of class "
593 + entry.getClass()
594 + " to registry "
595 + name);
596 }
597 }
598 }
599 catch (RegistryException e)
600 {
601 logger.error(
602 "DatabaseRegistryService: RegistryException while adding "
603 + entry.getName()
604 + "from "
605 + location,
606 e);
607 }
608
609 toDelete.remove(entry.getName());
610 }
611 }
612
613 count += fragCount;
614 }
615
616
617 i = toDelete.iterator();
618 while (i.hasNext())
619 {
620 String entryName = (String) i.next();
621
622 if ((verbose > 1) && logger.isDebugEnabled())
623 {
624 logger.debug(
625 "DatabaseRegistryService: removing entry " + entryName);
626 }
627
628
629
630
631 }
632
633 if ((verbose > 1) && logger.isDebugEnabled())
634 {
635 logger.debug(
636 "DatabaseRegistryService: Merged "
637 + count
638 + " entries and deleted "
639 + toDelete.size()
640 + " in "
641 + name);
642 }
643 }
644
645
646
647 /*** Refresh the state of the registry implementation. Should be called
648 * whenever the underlying fragments are modified
649 */
650 public void refresh()
651 {
652 synchronized (watcher)
653 {
654 Enumeration en = getNames();
655 while (en.hasMoreElements())
656 {
657 refresh((String) en.nextElement());
658 }
659 }
660 }
661
662 /***
663 * Load and unmarshal a RegistryFragment from the file
664 * @param file the absolute file path storing this fragment
665 */
666 public void loadFragment(String file )
667 {
668 try
669 {
670 RegistryFragment fragment = createFragment(file);
671
672 fragment.setChanged(true);
673
674
675 updateFragment(file, fragment);
676
677 }
678 catch (Throwable t)
679 {
680 logger.error(
681 "DatabaseRegistryService: Could not unmarshal: " + file,
682 t);
683 }
684 }
685
686 /***
687 * Read and unmarshal a fragment in memory
688 * @param name the name of this fragment
689 * @param persistent whether this fragment should be persisted on disk in
690 * the registry
691 */
692 public void createFragment(
693 String name,
694 Reader reader,
695 boolean persistent)
696 {
697 String file = null;
698
699 try
700 {
701 }
702 catch (Throwable t)
703 {
704 logger.error(
705 "DatabaseRegistryService: Could not create fragment: " + file, t);
706 }
707 finally
708 {
709 try
710 {
711 reader.close();
712 }
713 catch (Exception e)
714 {
715 logger.error(e);
716 }
717 }
718 }
719 /***
720 * Marshal and save a RegistryFragment to disk
721 * @param file the absolute file path storing this fragment
722 */
723 public void saveFragment(String file)
724 {
725
726 /***
727 * TODO I will implement this
728 * should go to database
729 */
730
731 }
732 /***
733 * Remove a fragment from storage
734 * @param file the absolute file path storing this fragment
735 */
736 public void removeFragment(String file)
737 {
738 RegistryFragment fragment = (RegistryFragment) fragments.get(file);
739
740 if (fragment != null)
741 {
742 synchronized (entryIndex)
743 {
744
745 Iterator i = entryIndex.keySet().iterator();
746 while (i.hasNext())
747 {
748 if (file.equals(entryIndex.get(i.next())))
749 {
750 i.remove();
751 }
752 }
753
754
755
756
757 fragment.clear();
758
759 fragments.remove(file);
760 }
761 }
762 }
763
764 /***
765 * Updates a fragment in storage and the associated entryIndex
766 */
767 protected void updateFragment(String name, RegistryFragment fragment)
768 {
769 synchronized (entryIndex)
770 {
771
772 Iterator i = entryIndex.keySet().iterator();
773 while (i.hasNext())
774 {
775 if (name.equals(entryIndex.get(i.next())))
776 {
777 i.remove();
778 }
779 }
780
781 fragments.put(name, fragment);
782
783
784
785 Enumeration enum = fragment.keys();
786 while (enum.hasMoreElements())
787 {
788 String strReg = (String) enum.nextElement();
789 Vector v = fragment.getEntries(strReg);
790 for (int counter = 0; counter < v.size(); counter++)
791 {
792 RegistryEntry str = (RegistryEntry) v.elementAt(counter);
793 entryIndex.put(str.getName(), name);
794 }
795 }
796 }
797 }
798
799
800 private static List getData(String name)
801 {
802 List list = null;
803 try
804 {
805 DBRegistry BaseClass = (DBRegistry) baseClass.get(name);
806 if (BaseClass != null)
807 {
808 list = BaseClass.getXREGDataFromDb();
809 }
810 else
811 {
812 logger.warn(
813 "DatabaseRegistryService: Base class for service " + name + " not found");
814 }
815 }
816 catch (Exception ex)
817 {
818 logger.warn(
819 "DatabaseRegistryService: Base class for service " + name + " not found");
820 }
821 return list;
822 }
823
824 private RegistryFragment createFragment(String regName)
825 {
826 RegistryFragment fragment = (RegistryFragment) fragments.get(regName);
827
828
829 if (fragment == null)
830 {
831 fragment = new RegistryFragment();
832 fragment.put(regName, new Vector());
833 }
834 else
835 {
836 Vector vectRegistry = (Vector) fragment.get(regName);
837 if (vectRegistry == null)
838 {
839 fragment.put(regName, new Vector());
840 }
841 }
842 List entries = getData(regName);
843 if (entries != null)
844 {
845 for (int i = 0; i < entries.size(); i++)
846 {
847 fragment.setEntry(regName, (RegistryEntry) entries.get(i));
848
849
850 fragment.setDirty(true);
851 }
852 }
853 else
854 {
855 logger.warn(
856 "DatabaseRegistryService:no data fouund for service " + name );
857
858 }
859 return fragment;
860
861 }
862 }