KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > jetspeed > services > registry > DatabaseRegistryService


1 /*
2  * Copyright 2000-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.jetspeed.services.registry;
18
19 // Java classes
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 //turbine stuff
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 // Jetspeed classes
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                 // either the entry was deleted or it does not exist
198
// in both cases, use the default fragment
199
fragmentName = (String) defaults.get(regName);
200             }
201
202             RegistryFragment fragment =
203                 (RegistryFragment) fragments.get(fragmentName);
204
205             //Fragment can be (and sometimes is, but should not be) null
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                 // mark this fragment so that it's persisted next time
236
// the registry watcher is running
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                     // mark this fragment so that it's persisted next time
274
// the registry watcher is running
275
fragment.setDirty(true);
276                 }
277             }
278
279             // the entry is physically removed, remove the dangling reference
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         //Ensure that the servlet service is initialized
295
TurbineServices.getInstance().initService(ServletService.SERVICE_NAME, conf);
296
297         ResourceService serviceConf =
298             ((TurbineServices) TurbineServices.getInstance()).getResources(SERVICE_NAME);
299
300         //build the map of default fragments, eahc registry must be associated
301
//with at least one fragment
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                 // add this name in the list of available registries
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         // changing the base will trigger a synchronous loading of the fragments
358
this.watcher.changeBase(names);
359
360         //Mark that we are done
361
setInit(true);
362
363         // load the registries
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         // Start the directory watcher thread and rely on its refresh process
401
// to completely load all registries
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             //Not yet...
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         // for each fragment...
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                 //remove this fragment entries from the delete list
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             //the fragment has some changes, iterate over its entries...
534
Vector entries = fragment.getEntries(regName);
535             //... if it has entries related to this regsistry,
536
if (entries != null)
537             {
538                 // for all these entries
539
Enumeration en2 = entries.elements();
540                 while (en2.hasMoreElements())
541                 {
542                     RegistryEntry entry = (RegistryEntry) en2.nextElement();
543                     // update or add the entry in the registry
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                                 // Initialize the entry index
575
this.entryIndex.put(entry.getName(), location);
576                                 ++fragCount;
577                             }
578                         }
579                         else
580                         {
581                             registry.addLocalEntry(entry);
582                             // Initialize the entry index
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                     //remove this entry from the delete list
609
toDelete.remove(entry.getName());
610                 }
611             }
612
613             count += fragCount;
614         }
615
616         //now delete the entries not found in any fragment
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             //TODO may be I will do it later
628
//it should delete only portlets which is coming from database
629

630             //registry.removeLocalEntry(entryName);
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     // FileRegistry interface
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             //mark this fragment as changed
672
fragment.setChanged(true);
673
674             // if we get here, we successfully loaded the new fragment
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); // At least log the exception.
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                 // clear the entry index
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                 // make sure the keys & entries are freed for this fragment
755
// only the entries not replaced by the next registry refresh will
756
// stay in memory
757
fragment.clear();
758                 // remove the actual fragment from memory
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             // remove the old keys
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             // store the new fragment
781
fragments.put(name, fragment);
782
783             // recreate the index entries (only this fragment)
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     //class specific implementation
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         //Fragment can be (and sometimes is, but should not be) null
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                 // mark this fragment so that it's persisted next time
849
// the registry watcher is running
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 }
Popular Tags