Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/slide/common/Namespace.java


1   /*
2    * $Header: /home/cvs/jakarta-slide/src/share/org/apache/slide/common/Namespace.java,v 1.65.2.1 2004/09/29 15:01:26 unico Exp $
3    * $Revision: 1.65.2.1 $
4    * $Date: 2004/09/29 15:01:26 $
5    *
6    * ====================================================================
7    *
8    * Copyright 1999-2002 The Apache Software Foundation 
9    *
10   * Licensed under the Apache License, Version 2.0 (the "License");
11   * you may not use this file except in compliance with the License.
12   * You may obtain a copy of the License at
13   *
14   *     http://www.apache.org/licenses/LICENSE-2.0
15   *
16   * Unless required by applicable law or agreed to in writing, software
17   * distributed under the License is distributed on an "AS IS" BASIS,
18   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19   * See the License for the specific language governing permissions and
20   * limitations under the License.
21   *
22   */
23  
24  package org.apache.slide.common;
25  
26  import java.lang.reflect.Constructor;
27  import java.lang.reflect.Method;
28  import java.util.Enumeration;
29  import java.util.Hashtable;
30  import java.util.Vector;
31  import javax.transaction.Status;
32  import javax.transaction.SystemException;
33  import javax.transaction.TransactionManager;
34  import org.apache.slide.authenticate.CredentialsToken;
35  import org.apache.slide.content.ContentInterceptor;
36  import org.apache.slide.extractor.Extractor;
37  import org.apache.slide.extractor.ExtractorManager;
38  import org.apache.slide.store.ContentStore;
39  import org.apache.slide.store.DefaultIndexer;
40  import org.apache.slide.store.IndexStore;
41  import org.apache.slide.store.LockStore;
42  import org.apache.slide.store.NodeStore;
43  import org.apache.slide.store.RevisionDescriptorStore;
44  import org.apache.slide.store.RevisionDescriptorsStore;
45  import org.apache.slide.store.SecurityStore;
46  import org.apache.slide.store.SequenceStore;
47  import org.apache.slide.store.Store;
48  import org.apache.slide.structure.ObjectAlreadyExistsException;
49  import org.apache.slide.structure.SubjectNode;
50  import org.apache.slide.transaction.SlideTransactionManager;
51  import org.apache.slide.util.conf.Configurable;
52  import org.apache.slide.util.conf.Configuration;
53  import org.apache.slide.util.conf.ConfigurationException;
54  import org.apache.slide.util.logger.Logger;
55  
56  /**
57   * A Namespace contains a hierarchically organized tree of information.
58   *
59   * <p>
60   *   Objects in the namespace are generally referred to as <i>Nodes</i>. Nodes
61   *   may have a parent, children, content and meta-data. They can also be
62   *   versioned (so that multiple revisions of the object's content and
63   *   metadata are stored) and locked (so that only specific principals are
64   *   allowed to read or modify the object). In addition, access control
65   *   information can be assigned to every node.
66   * </p>
67   * <p>
68   *   Nodes in the hierarchy are identified by their URI (Unique Resource
69   *   Identifier). A URI is analogous to a file path in traditional file
70   *   systems. For example:
71   *   <pre>
72   *     /users/john/documents/my_document.txt
73   *   </pre>
74   *   As you can see, the slash (&quot;/&quot;) is used to separate nodes in the path.
75   * </p>
76   * <p>
77   *   Client applications can not access a Namespace object directly. Instead,
78   *   access must be requested from the {@link Domain Domain}, which will hand
79   *   out a proxy object ({@link NamespaceAccessToken NamespaceAccessToken})
80   *   that enables the client application to access the namespace using the
81   *   helpers.
82   * </p>
83   * <p>
84   *   Namespaces are necessarily self-contained. What this means is that a
85   *   namespace cannot reference or contain links to another namespace. A
86   *   namespace is typically assigned per-application, which effectively
87   *   isolates it's data and security context from those of other applications.
88   * </p>
89   *
90   * @version $Revision: 1.65.2.1 $
91   */
92  public final class Namespace {
93      
94      
95      // -------------------------------------------------------------- Constants
96      
97      
98      public static final String REFERENCE = "reference";
99      public static final String NODE_STORE = "nodestore";
100     public static final String SECURITY_STORE = "securitystore";
101     public static final String LOCK_STORE = "lockstore";
102     public static final String REVISION_DESCRIPTORS_STORE =
103         "revisiondescriptorsstore";
104     public static final String REVISION_DESCRIPTOR_STORE =
105         "revisiondescriptorstore";
106     public static final String CONTENT_STORE = "contentstore";
107     public static final String PROPERTIES_INDEX_STORE = "propertiesindexer";
108     public static final String CONTENT_INDEX_STORE = "contentindexer";
109     public static final String SEQUENCE_STORE = "sequencestore";
110     
111     
112     /**
113      * Log channel for logger
114      */
115     private static final String LOG_CHANNEL = Namespace.class.getName();
116     
117     protected static final String I_CREATESTORELISTENERCLASS         = "createStoreListenerClass";
118     protected static final String I_CREATESTORELISTENERCLASS_DEFAULT = "org.apache.slide.webdav.util.UriHandler";
119     
120     protected static Class createStoreListenerClass;
121     
122     
123     static {
124         try {
125             String createStoreListenerClassName = Domain.getParameter(I_CREATESTORELISTENERCLASS, I_CREATESTORELISTENERCLASS_DEFAULT);
126             createStoreListenerClass = Class.forName( createStoreListenerClassName );
127         }
128         catch( Exception x ) {
129             Domain.warn( "Loading of create_store_listener class failed: "+x.getMessage() );
130         }
131     }
132     
133     // ----------------------------------------------------- Instance Variables
134     
135     
136     /**
137      * Namespace name.
138      */
139     private String name;
140     
141     
142     /**
143      * classname of the search implementation
144      */
145     private String searchClassName;
146     
147     
148     /**
149      * Static Vector which holds a reference, and provides access to all
150      * the services instances used by the Slide namespace.
151      */
152     private transient Vector connectedServices;
153     
154     
155     /**
156      * Registered DescriptorStores on this Namespace.
157      */
158     private transient Hashtable stores;
159     
160     
161     /**
162      * Current namespace configuration.
163      */
164     private NamespaceConfig config;
165     
166     
167     /**
168      * Uri cache.
169      */
170     private Hashtable uriCache;
171     
172     
173     /**
174      * Default descriptors store classname.
175      */
176     private String defaultStoreClassname =
177         "org.apache.slide.store.ExtendedStore";
178     
179     
180     /**
181      * Transaction manager associated with this namespace.
182      */
183     private TransactionManager transactionManager =
184         new SlideTransactionManager();
185     
186     
187     /**
188      * Logger.
189      */
190     private Logger logger;
191     
192     
193     /**
194      * Application logger.
195      */
196     private Logger applicationLogger;
197     
198     
199     // ------------------------------------------------------------ Constructor
200     
201     
202     /**
203      * Constructor.
204      */
205     Namespace() {
206         stores = new Hashtable();
207         connectedServices = new Vector();
208         name = new String();
209         uriCache = new Hashtable();
210     }
211     
212     
213     // ------------------------------------------------------------- Properties
214     
215     
216     /**
217      * Sets the qualified name of the namespace.
218      *
219      * @param name Name of the namespace
220      */
221     public void setName(String name) {
222         this.name = name;
223     }
224     
225     
226     /**
227      * Gets the qulified name of the namespace.
228      *
229      * @return String Namespace name
230      */
231     public String getName() {
232         return name;
233     }
234     
235     
236     /**
237      * Method setSearchClassName
238      *
239      * @param    searchClassName     classname of the search implementation
240      */
241     public void setSearchClassName (String searchClassName) {
242         this.searchClassName = searchClassName;
243     }
244     
245     
246     /**
247      * Method getSearchClassName
248      *
249      * @return   classname of the search implementation
250      */
251     public String getSearchClassName()  {
252         return searchClassName;
253     }
254     
255     
256     /**
257      * Returns the namespace configuration.
258      *
259      * @return NamespaceConfig Namespace configuration
260      */
261     public NamespaceConfig getConfig() {
262         return config;
263     }
264     
265     
266     /**
267      * Enumerate all scopes managed by this namespace.
268      *
269      * @return     return an enumeration of all scopes
270      */
271     public Enumeration enumerateScopes() {
272         return stores.keys();
273     }
274     
275     
276     
277     /**
278      * Transaction manager accessor.
279      */
280     public TransactionManager getTransactionManager() {
281         return transactionManager;
282     }
283     
284     
285     /**
286      * Return the current logger.
287      */
288     public Logger getLogger() {
289         if (logger != null)
290             return logger;
291         else
292             return Domain.getLogger();
293     }
294     
295     
296     /**
297      * Set the logger used by this namespace.
298      */
299     public void setLogger(Logger logger) {
300         this.logger = logger;
301         if (transactionManager instanceof SlideTransactionManager) {
302             ((SlideTransactionManager) transactionManager).setLogger(logger);
303         }
304     }
305     
306     
307     /**
308      * Return the current application logger.
309      */
310     public Logger getApplicationLogger() {
311         if (applicationLogger != null)
312             return applicationLogger;
313         else if (logger != null)
314             return logger;
315         else
316             return Domain.getLogger();
317     }
318     
319     
320     /**
321      * Set the logger used by this namespace.
322      */
323     public void setApplicationLogger(Logger logger) {
324         this.applicationLogger = logger;
325     }
326     
327     
328     // --------------------------------------------------------- Public Methods
329     
330     
331     /**
332      * Used to register a Store in the namespace for the specified scope.
333      * First, the function instantiate the Store, then gives it
334      * its init parameters. It is then stored in the stores
335      * Hashtable, associated with the given scope.
336      *
337      * @param storeClass Class of the Data Source
338      * @param parameters Init parameters for the Data Source
339      * @param scope Scope for which the Data Source is registered
340      * @param childStores Instances of the typed stores
341      * @exception ServiceRegistrationFailed An error occured during
342      * instantiation of the service
343      * @exception ServiceParameterErrorException Incorrect service parameter
344      * @exception ServiceParameterMissingException Service parameter missing
345      */
346     public void registerStore(String storeName, Class storeClass,
347                               Hashtable parameters, Scope scope,
348                               Hashtable childStores)
349         throws ServiceRegistrationFailedException,
350         ServiceParameterErrorException, ServiceParameterMissingException {
351         if (!stores.containsKey(scope)) {
352             try {
353                 Store store = (Store) storeClass.newInstance();
354                 store.setName(storeName);
355                 store.setParameters(parameters);
356                 stores.put(scope, store);
357                 
358                 // assign NodeStore
359                 NodeStore nodeStore =
360                     (NodeStore) dereferenceStore (NODE_STORE, childStores);
361                 
362                 store.setNodeStore (nodeStore);
363                 
364                 // assign SecurityStore
365                 SecurityStore securityStore =
366                     (SecurityStore) dereferenceStore (SECURITY_STORE, childStores);
367                 
368                 store.setSecurityStore (securityStore);
369                 
370                 // assign LockStore
371                 LockStore lockStore =
372                     (LockStore) dereferenceStore (LOCK_STORE, childStores);
373                 
374                 store.setLockStore (lockStore);
375                 
376                 // assign RevisionDescriptorsStore
377                 RevisionDescriptorsStore revisionDescriptorsStore =
378                     (RevisionDescriptorsStore) dereferenceStore
379                     (REVISION_DESCRIPTORS_STORE, childStores);
380                 
381                 store.setRevisionDescriptorsStore (revisionDescriptorsStore);
382                 
383                 // assign RevisionDescriptorStore
384                 RevisionDescriptorStore revisionDescriptorStore =
385                     (RevisionDescriptorStore) dereferenceStore
386                     (REVISION_DESCRIPTOR_STORE, childStores);
387                 
388                 store.setRevisionDescriptorStore (revisionDescriptorStore);
389                 
390                 // assign ContentStore
391                 ContentStore contentStore =
392                     (ContentStore) dereferenceStore (CONTENT_STORE, childStores);
393                 
394                 store.setContentStore (contentStore);
395                 
396                 // assign PropertiesIndexStore
397                 IndexStore propertiesIndexer =
398                     (IndexStore) dereferenceStore (PROPERTIES_INDEX_STORE, childStores);
399                 
400                 // if not configured, take the default indexer
401                 if (propertiesIndexer == null) {
402                     propertiesIndexer = new DefaultIndexer (revisionDescriptorStore);
403                     childStores.put (PROPERTIES_INDEX_STORE, propertiesIndexer);
404                 }
405                 
406                 store.setPropertiesIndexer (propertiesIndexer);
407                 
408                 // assign ContentIndexStore
409                 IndexStore contentIndexer =
410                     (IndexStore) dereferenceStore (CONTENT_INDEX_STORE, childStores);
411                 
412                 // if not configured, take the default indexer
413                 if (contentIndexer == null) {
414                     contentIndexer = new DefaultIndexer (contentStore);
415                     childStores.put (CONTENT_INDEX_STORE, contentIndexer);
416                 }
417                 
418                 store.setContentIndexer (contentIndexer);
419                 
420                 // assign SequenceStore
421                 SequenceStore sequenceStore =
422                     (SequenceStore) dereferenceStore (SEQUENCE_STORE, childStores);
423                 
424                 store.setSequenceStore(sequenceStore);
425                 
426                 // set the scope in the father and child stores
427                 store.setScope(scope);
428                 
429                 // call the create_store_listener
430                 notifyStoreCreated( this.name, scope.toString(), storeName );
431                 
432             } catch(InstantiationException e) {
433                 throw new ServiceRegistrationFailedException
434                     (storeClass);
435             } catch(IllegalAccessException e) {
436                 throw new ServiceRegistrationFailedException
437                     (storeClass);
438             } catch(NullPointerException e) {
439                 throw new ServiceRegistrationFailedException
440                     (storeClass);
441             } catch(ClassCastException e) {
442                 // TEMP
443                 getLogger().log(e,LOG_CHANNEL, Logger.ERROR);
444                 // --TEMP
445                 throw new ServiceRegistrationFailedException
446                     (storeClass);
447             }
448             
449         }
450     }
451     
452     
453     Object dereferenceStore (String storeType, Hashtable childStores) {
454         Object result;
455         
456         Object o = childStores.get(storeType);
457         if (o instanceof String) {
458             result = childStores.get(o);
459         } else {
460             result = o;
461         }
462         return result;
463     }
464     
465     
466     /**
467      * At the end of the service registration, this service is called to
468      * perform any required initialization task.
469      *
470      * @exception ServicesInitializationFailedException One or more
471      * exception occured while initializing services
472      */
473     public void initializeServices()
474         throws ServicesInitializationFailedException {
475         
476         // We create the nested exception which will hold all thrown exception
477         // during the initialization process.
478         ServicesInitializationFailedException nestedException
479             = new ServicesInitializationFailedException();
480         
481         // Initializing DesciptorsStores
482         Enumeration serviceList = stores.elements();
483         while (serviceList.hasMoreElements()) {
484             Service service = (Service) serviceList.nextElement();
485             try {
486                 getLogger().log("Initializing Store " + service,LOG_CHANNEL,Logger.INFO);
487                 service.setNamespace(this);
488                 service.initialize(new NamespaceAccessTokenImpl(this));
489             } catch (ServiceInitializationFailedException e) {
490                 // We add the exception which just occured to the
491                 // nested exception
492                 nestedException.addException(e);
493             }
494         }
495         
496         // If the nested exception is not empty, we throw it.
497         if (!nestedException.isEmpty()) {
498             throw nestedException;
499         }
500         
501     }
502     
503     
504     /**
505      * Reinitialize namespace.
506      */
507     public void clearNamespace() {
508         stores.clear();
509     }
510     
511     
512     /**
513      * Connects a data source on demand.
514      *
515      * @param service Service on which a connection attempt will be made
516      * @param token the credentials token containing e.g. the credential
517      * @exception ServiceConnectionFailedException Error connecting service
518      * @exception ServiceAccessException Unspecified low level service
519      * access exception
520      */
521     public void connectService(Service service, CredentialsToken token)
522         throws ServiceConnectionFailedException, ServiceAccessException {
523         // Try to connect ...
524         boolean newConnection = service.connectIfNeeded(token);
525         
526         // If successfull (ie, no exception was thrown), we add it to the list
527         // of the connected components.
528         if (newConnection) {
529             connectedServices.addElement(service);
530         }
531     }
532     
533     
534     /**
535      * Disconnects all services.
536      *
537      * @exception ServicesShutDownFailedException Error disconnecting one or
538      * more services
539      */
540     public void disconnectServices()
541         throws ServicesShutDownFailedException {
542         
543         // We create the nested exception which will hold all thrown exception
544         // during shut down of services.
545         ServicesShutDownFailedException nestedException
546             = new ServicesShutDownFailedException();
547         
548         for (int i=0; i<connectedServices.size(); i++) {
549             try {
550                 Service service = (Service) connectedServices.elementAt(i);
551                 if (service.isConnected()) {
552                     getLogger().log("Shutting down service " + service,LOG_CHANNEL,Logger.INFO);
553                     service.disconnect();
554                 }
555             } catch (ServiceDisconnectionFailedException e) {
556                 nestedException.addException(e);
557             } catch (ServiceAccessException e) {
558                 nestedException.addException(e);
559             }
560         }
561         connectedServices.removeAllElements();
562         
563         // If the nested exception is not empty, we throw it.
564         if (!nestedException.isEmpty()) {
565             throw nestedException;
566         }
567         
568     }
569     
570     
571     /**
572      * Remove a Store from the registry.
573      *
574      * @param scope Scope to disconnect
575      * @exception ServiceDisconnctionFailedException Error disconnecting
576      * DescriptorsStore
577      * @exception ServiceAccessException Unspecified error during
578      * service access
579      */
580     public void unregisterStore(Scope scope)
581         throws ServiceDisconnectionFailedException, ServiceAccessException {
582         if (stores.containsKey(scope)) {
583             Store store = (Store) stores.get(scope);
584             if (store.isConnected()) {
585                 store.disconnect();
586                 connectedServices.removeElement(store);
587             }
588             stores.remove(scope);
589             store = null;
590         }
591     }
592     
593     
594     /**
595      * Get the Data Source associated with the given scope, if any.
596      * In contrary to the retrieveStore method, this methos does not
597      * perform a connection.
598      *
599      * @param scope Scope to match
600      */
601     public Store getStore(Scope scope) {
602         Store store = null;
603         if (stores.containsKey(scope)) {
604             store = (Store) stores.get(scope);
605         }
606         return store;
607     }
608     
609     
610     /**
611      * Get the Data Source associated with the given scope, if any and
612      * connect to the store.
613      *
614      * @param scope Scope to match
615      * @param token the Credeantials token containing e.g. the credential
616      * @exception ServiceConnectionFailedException Connection to Store failed
617      * @exception ServiceAccessException Unspecified service access exception
618      */
619     public Store retrieveStore(Scope scope, CredentialsToken token)
620         throws ServiceConnectionFailedException, ServiceAccessException {
621         Store store = getStore(scope);
622         if (store != null) {
623             connectService(store, token);
624         }
625         return store;
626     }
627     
628     
629     /**
630      * Builds a new uri object to access this namespace. This call will
631      * return a Uri which doesn't have its token field set. The store should
632      * accept such Uri as valid, and bypass any check that is made based on the
633      * state.
634      *
635      * @param uri Requested Uri
636      * @return Uri
637      */
638     public Uri getUri(String uri) {
639         return getUri(null, uri);
640     }
641     
642     
643     /**
644      * Builds a new uri object to access this namespace.
645      *
646      * @param token SlideToken
647      * @param uri Requested Uri
648      * @return Uri
649      */
650     public Uri getUri(SlideToken token, String uri) {
651         return getUri(token, uri, token==null
652                           ?false
653                           :token.isForceStoreEnlistment());
654     }
655     
656     
657     /**
658      * Builds a new uri object to access this namespace.
659      *
660      * @param token SlideToken
661      * @param uri Requested Uri
662      * @param forcedEnlistment may differ from the value set in token
663      * @return Uri
664      */
665     public Uri getUri(SlideToken token, String uri, boolean forcedEnlistment) {
666         
667         Uri result = null;
668         Object temp = null;
669         temp = uriCache.get(uri);
670         if (temp == null) {
671             result = new Uri(token, this, uri);
672             uriCache.put(uri, result);
673             if (uriCache.size() > 10000) {
674                 clearUriCache();
675             }
676         } else {
677             result = (Uri) temp;
678             result = result.cloneObject();
679             result.setToken(token);
680             result.reconnectServices();
681         }
682         
683         // if a different forceEnlistment value want to be used
684         // wrap the used token to reflect the different value
685         if (token != null && token.isForceStoreEnlistment() != forcedEnlistment) {
686             SlideToken wToken = new SlideTokenWrapper(token);
687             wToken.setForceStoreEnlistment(forcedEnlistment);
688             result.setToken(wToken);
689         }
690         
691         return result;
692         
693     }
694     
695     
696     /**
697      * Clear uri cache.
698      */
699     void clearUriCache() {
700         uriCache.clear();
701     }
702     
703     
704     /**
705      * Get content interceptors associated with this namespace.
706      */
707     public ContentInterceptor[] getContentInterceptors() {
708         return config.getContentInterceptors();
709     }
710     
711     
712     // -------------------------------------------------------- Package Methods
713     
714     
715     /**
716      * Parses the contents of the specified definition object, and uses that
717      * info to initialize the namespace.
718      *
719      * @param definition Definiton of the scopes and stores of
720      * the namespace
721      * @exception SlideException Something went wrong during registry or
722      * services initialization
723      * @exception ConfigurationException Error parsing configuration file
724      */
725     void loadDefinition(Configuration definition)
726         throws SlideException, ConfigurationException {
727         
728         getLogger().log("Loading namespace definition",LOG_CHANNEL,Logger.INFO);
729         
730         // Loading stores
731         
732         Hashtable storesClass = new Hashtable();
733         Hashtable storesParameters = new Hashtable();
734         Hashtable childStores = new Hashtable();
735         
736         Enumeration storeDefinitions =
737             definition.getConfigurations("store");
738         
739         while (storeDefinitions.hasMoreElements()) {
740             loadStoreDefinition
741                 ((Configuration) storeDefinitions.nextElement(),
742                  storesClass, storesParameters, childStores);
743         }
744         
745         Enumeration scopeDefinitions =
746             definition.getConfigurations("scope");
747         
748         while (scopeDefinitions.hasMoreElements()) {
749             loadScopeDefinition
750                 ((Configuration) scopeDefinitions.nextElement(),
751                  storesClass, storesParameters, childStores);
752         }
753         
754         // Initialize all loaded services.
755         initializeServices();
756         
757     }
758     
759     
760     /**
761      * Parses the contents of the specified reader, and uses that info to
762      * initialize the specified Slide namespace.
763      *
764      * @param namespaceBaseDataDefinition Namespace base data
765      * @exception SlideException Something went wrong during registry or
766      * services initialization
767      */
768     void loadBaseData(Configuration namespaceBaseDataDefinition)
769         throws SlideException, ConfigurationException {
770         
771         getLogger().log("Loading namespace " + getName() + " base data",LOG_CHANNEL,Logger.INFO);
772         
773         // Load Namespace Base Data
774         try {
775             // start transaction for temp object creation
776             getTransactionManager().begin();
777             
778             SlideToken slideToken = new SlideTokenImpl(new CredentialsToken(""));
779             slideToken.setForceStoreEnlistment(true);
780             
781             // First, we create the root node
782             Uri rootUri = getUri(slideToken, "/");
783             SubjectNode rootNode = new SubjectNode("/");
784             try {
785                 rootUri.getStore().createObject(rootUri, rootNode);
786             } catch (ObjectAlreadyExistsException e) {
787                 // abort the failed transaction
788                 getTransactionManager().rollback();
789                 // start a new one to continue processing
790                 getTransactionManager().begin();
791             }
792             
793             // end transaction for temp object creation
794             getTransactionManager().commit();
795             
796             getLogger().log("Init namespace " + getName() + " configuration",LOG_CHANNEL,Logger.INFO);
797             
798             // Create the dummy configuration
799             config.initializeAsDummyConfig(this);
800             
801             // Create the Access token
802             NamespaceAccessToken token = new NamespaceAccessTokenImpl(this);
803             
804             // start the transaction, NOTE some operations are outside this TA
805             token.begin();
806             
807             getLogger().log("Import data into namespace " + getName(),LOG_CHANNEL,Logger.INFO);
808             token.importData(slideToken, namespaceBaseDataDefinition);
809             
810             // end the transaction, NOTE some operations are outside this TA
811             token.commit();
812             
813             // start transaction for temp object removal
814             getTransactionManager().begin();
815             
816             getLogger().log("Finish init namespace " + getName() + " configuration",LOG_CHANNEL,Logger.INFO);
817             
818             // And remove the all permission from the root node
819             rootNode =
820                 (SubjectNode) rootUri.getStore().retrieveObject(rootUri);
821             rootUri.getStore().storeObject(rootUri, rootNode);
822             
823             // end transaction for temp object removal
824             getTransactionManager().commit();
825             
826         } catch (SlideException e) {
827             // If that occurs, then most likely the base config was
828             // already done before
829             e.printStackTrace();
830             getLogger().log("Namespace base configuration was already done before",LOG_CHANNEL,Logger.INFO);
831             try {
832                 if (getTransactionManager().getStatus()==Status.STATUS_ACTIVE)
833                     getTransactionManager().rollback();
834             }
835             catch (SystemException ex) {
836                 getLogger().log("Could not rollback namespace base configuration: " + ex.toString(),LOG_CHANNEL,Logger.WARNING);
837             }
838         } catch (Exception e) {
839             getLogger().log("Unable to read Namespace base configuration file : ",LOG_CHANNEL,Logger.ERROR);
840             getLogger().log(e,LOG_CHANNEL, Logger.ERROR);
841             // Unable to load the base configuration XML file.
842             // Log the event, and hope it was already done before.
843             try {
844                 if (getTransactionManager().getStatus()==Status.STATUS_ACTIVE)
845                     getTransactionManager().rollback();
846             }
847             catch (SystemException ex) {
848                 getLogger().log("Could not rollback namespace base configuration after load error: " + ex.toString(),LOG_CHANNEL,Logger.WARNING);
849             }
850         }
851     }
852     
853     
854     /**
855      * Parses the contents of the specified reader, and uses that info to
856      * initialize the specified Slide namespace.
857      *
858      * @param namespaceConfigurationDefinition The configuration to load.
859      * @exception SlideException Something went wrong during registry or
860      * services initialization
861      */
862     void loadConfiguration(Configuration namespaceConfigurationDefinition)
863         throws SlideException {
864         
865         getLogger().log("Loading namespace " + getName() + " configuration",LOG_CHANNEL,Logger.INFO);
866         
867         // Load Namespace Config
868         config = new NamespaceConfig();
869         config.initializeNamespaceConfig(this,
870                                          namespaceConfigurationDefinition);
871         
872     }
873     
874     
875     /**
876      * Parses the contents of the specified reader, and uses that info to
877      * initialize the specified Slide namespace.
878      *
879      * @param namespaceConfigurationDefinition Namespace configuration
880      * @exception SlideException Something went wrong during registry or
881      * services initialization
882      */
883     void loadParameters(Configuration namespaceConfigurationDefinition)
884         throws SlideException {
885         
886         getLogger().log("Loading namespace " + getName() + " parameters",LOG_CHANNEL,Logger.INFO);
887         
888         // Load Namespace Config
889         config = new NamespaceConfig();
890         config.initializeNamespaceParameters(this,
891                                              namespaceConfigurationDefinition);
892         
893     }
894     
895     
896     void loadExtractors(Configuration namespaceExtractorsDefinition) 
897       throws SlideException {
898         
899         getLogger().log("Loading namespace " + getName() + " extractors",LOG_CHANNEL,Logger.INFO);
900         
901         Enumeration extractorConfigs = namespaceExtractorsDefinition.getConfigurations("extractor");
902         while (extractorConfigs.hasMoreElements()) {
903             Configuration extractorConfig = (Configuration) extractorConfigs.nextElement();
904             String classname = extractorConfig.getAttribute("classname");
905             String uri = extractorConfig.getAttribute("uri", null);
906             String contentType = extractorConfig.getAttribute("content-type", null);
907             String namespace = getName();
908             try {
909                 Class extractorClass = Class.forName(classname);
910                 Extractor extractor = null;
911                 Constructor extractorConstructor = extractorClass.getConstructor(new Class[] { String.class, String.class, String.class } );
912                 extractor = (Extractor)extractorConstructor.newInstance(new String[] { uri, contentType, namespace });
913                 if ( extractor instanceof Configurable ) {
914                     ((Configurable)extractor).configure(extractorConfig.getConfiguration("configuration"));
915                 }
916                 ExtractorManager.getInstance().addExtractor(extractor);
917             } catch (ClassCastException e) {
918                 throw new ConfigurationException("Extractor '"+classname+"' is not of type Extractor", namespaceExtractorsDefinition);
919             } catch (ConfigurationException e) {
920                 throw e;
921             } catch (Exception e) {
922                 throw new ConfigurationException("Extractor '"+classname+"' could not be loaded", namespaceExtractorsDefinition);
923             }
924         }
925     }
926     
927     // -------------------------------------------------------- Private Methods
928     
929     
930     /**
931      * Parse the store definition.
932      *
933      * @param storeDefinition store definition
934      * @param storesClass Class names of the stores
935      * @param storesParameters Parameters of the stores
936      * @param childStores Child stores
937      * @exception ConfigurationException Error parsing configuration file
938      * @exception SlideException Error loading the specified class
939      */
940     private void loadStoreDefinition
941         (Configuration storeDefinition,
942          Hashtable storesClass,
943          Hashtable storesParameters,
944          Hashtable childStores)
945         throws ConfigurationException, SlideException {
946         
947         String storeName = storeDefinition.getAttribute("name");
948         String storeClassname = defaultStoreClassname;
949         
950         try {
951             storeClassname = storeDefinition.getAttribute("classname");
952         } catch (ConfigurationException e) {
953         }
954         
955         Enumeration storeParametersDefinitions =
956             storeDefinition.getConfigurations("parameter");
957         
958         // Load descriptors store class
959         Class storeClass = null;
960         try {
961             storeClass = Class.forName(storeClassname);
962         } catch (Exception e) {
963             getLogger().log(e,LOG_CHANNEL, Logger.ERROR);
964             throw new SlideException(e.getMessage());
965         }
966         storesClass.put(storeName, storeClass);
967         
968         // Load descriptor store parameters
969         Hashtable storeParameters = new Hashtable();
970         while (storeParametersDefinitions.hasMoreElements()) {
971             Configuration parameterDefinition = (Configuration)
972                 storeParametersDefinitions.nextElement();
973             String parameterName = parameterDefinition.getAttribute("name");
974             String parameterValue = parameterDefinition.getValue();
975             storeParameters.put(parameterName, parameterValue);
976         }
977         
978         storesParameters.put(storeName, storeParameters);
979         
980         // Now reading the "child" stores
981         
982         Hashtable currentStoreChildStores = new Hashtable();
983                 
984         // Loading node store (if any)
985         getChildStore (storeDefinition, NODE_STORE, currentStoreChildStores, storeParameters);
986         
987         // Loading security store (if any)
988         getChildStore (storeDefinition, SECURITY_STORE, currentStoreChildStores, storeParameters);
989         
990         // Loading lock store (if any)
991         getChildStore (storeDefinition, LOCK_STORE, currentStoreChildStores, storeParameters);
992         
993         // Loading revision descriptors store (if any)
994         getChildStore (storeDefinition, REVISION_DESCRIPTORS_STORE, currentStoreChildStores, storeParameters);
995         
996         // Loading revision descriptor store (if any)
997         getChildStore (storeDefinition, REVISION_DESCRIPTOR_STORE, currentStoreChildStores, storeParameters);
998         
999         // Loading content store (if any)
1000        getChildStore (storeDefinition, CONTENT_STORE, currentStoreChildStores, storeParameters);
1001        
1002        // Loading descriptorindexstore store (if any)
1003        getChildStore (storeDefinition, PROPERTIES_INDEX_STORE, currentStoreChildStores, storeParameters);
1004        
1005        // Loading contentindexstore store (if any)
1006        getChildStore (storeDefinition, CONTENT_INDEX_STORE, currentStoreChildStores, storeParameters);
1007        
1008        // load default indexer, if no indexer defined
1009        
1010        // Loading sequence store (if any)
1011        getChildStore (storeDefinition, SEQUENCE_STORE, currentStoreChildStores, storeParameters);
1012
1013        childStores.put(storeName, currentStoreChildStores);
1014        
1015    }
1016    
1017    private void getChildStore(Configuration storeDefinition, String key, Hashtable currentStoreChildStores, Hashtable storeParameters) throws SlideException
1018    {
1019        Configuration localStoreDefinition;
1020        try {
1021            localStoreDefinition = storeDefinition.getConfiguration(key);
1022        } catch (ConfigurationException e) {
1023            return;
1024            // silently ignore as this only indicates there is no such store defined
1025        }
1026        try {
1027            try {
1028                Configuration referenceDefinition =
1029                    localStoreDefinition.getConfiguration(REFERENCE);
1030                currentStoreChildStores.put
1031                    (key, referenceDefinition.getAttribute("store"));
1032                getLogger().log(key + " references " + referenceDefinition.getAttribute("store"),LOG_CHANNEL,Logger.INFO);
1033            } catch (ConfigurationException ex) {
1034                getLogger().log(key + ": " + localStoreDefinition.getAttribute("classname"),LOG_CHANNEL,Logger.INFO);
1035                Service store =
1036                    loadChildStore(localStoreDefinition,
1037                                   storeParameters);
1038                if (store != null) {
1039                    currentStoreChildStores.put(key, store);
1040                }
1041            }
1042        } catch (ConfigurationException e) {
1043            getLogger().log("Exception while loading "+key+"!", e, LOG_CHANNEL, Logger.WARNING);
1044        }
1045    }
1046    
1047    
1048    /**
1049     * Load a child descriptors store.
1050     *
1051     * @param childStoreDefinition XML definition of the child store
1052     * @param fatherParameters     XML parameters defined for the father
1053     * @return Service Instance of the child store
1054     * @exception ConfigurationException Error parsing configuration file
1055     * @exception SlideException Error loading the specified class
1056     */
1057    private Service loadChildStore(Configuration childStoreDefinition,
1058                                   Hashtable fatherParameters)
1059        throws ConfigurationException, SlideException {
1060        
1061        // Load classname
1062        String childStoreClassname =
1063            childStoreDefinition.getAttribute("classname");
1064        
1065        // Load descriptors store class
1066        Service childStore = null;
1067        try {
1068            Class childStoreClass =
1069                Class.forName(childStoreClassname);
1070            childStore = (Service) childStoreClass.newInstance();
1071        } catch (Exception e) {
1072            getLogger().log(e,LOG_CHANNEL, Logger.ERROR);
1073            return null;
1074        }
1075        
1076        // Retrieve parent parameters
1077        Hashtable childStoreParameters = new Hashtable();
1078        Enumeration fatherParametersKeys = fatherParameters.keys();
1079        while (fatherParametersKeys.hasMoreElements()) {
1080            Object key = fatherParametersKeys.nextElement();
1081            Object value = fatherParameters.get(key);
1082            childStoreParameters.put(key, value);
1083        }
1084        
1085        // Load parameters
1086        Enumeration childStoreParametersDefinitions =
1087            childStoreDefinition.getConfigurations("parameter");
1088        while (childStoreParametersDefinitions.hasMoreElements()) {
1089            Configuration parameterDefinition = (Configuration)
1090                childStoreParametersDefinitions.nextElement();
1091            String parameterName = parameterDefinition.getAttribute("name");
1092            String parameterValue = parameterDefinition.getValue();
1093            childStoreParameters.put(parameterName, parameterValue);
1094        }
1095        childStore.setParameters(childStoreParameters);
1096        
1097        return childStore;
1098        
1099    }
1100    
1101    
1102    /**
1103     * Parse the content store definition.
1104     *
1105     * @param storesClass Class names of the descriptors stores
1106     * @param storesParameters Parameters of the descriptors stores
1107     * @param childStores Child stores instances
1108     * @exception ConfigurationException Error parsing configuration file
1109     * @exception UnknownServiceDeclarationException Reference to
1110     * unknown service
1111     * @exception ServiceParameterErrorException Service parameter error
1112     * @exception ServiceParameterMissingException Service parameter missing
1113     * @exception ServiceRegistrationFailedException Error registering service
1114     */
1115    private void loadScopeDefinition(Configuration scopeDefinition,
1116                                     Hashtable storesClass,
1117                                     Hashtable storesParameters,
1118                                     Hashtable childStores)
1119        throws ConfigurationException, UnknownServiceDeclarationException,
1120        ServiceParameterErrorException, ServiceParameterMissingException,
1121        ServiceRegistrationFailedException {
1122        
1123        String match = scopeDefinition.getAttribute("match");
1124        
1125        // First, we get the correct class and parameters from the Hashtables.
1126        String storeName = scopeDefinition.getAttribute("store");
1127        
1128        if (storeName != null) {
1129            if ((!storesClass.containsKey(storeName)) ||
1130                    (!storesParameters.containsKey(storeName))) {
1131                throw new UnknownServiceDeclarationException(storeName);
1132            }
1133            registerStore(storeName,
1134                              (Class) storesClass.get(storeName),
1135                              (Hashtable) storesParameters.get(storeName),
1136                          new Scope(match),
1137                              (Hashtable) childStores.get(storeName));
1138            getLogger().log("Registering Store "
1139                                + storeName
1140                                + " ("
1141                                + storesClass.get(storeName)
1142                                + ") with parameters "
1143                                + storesParameters.get(storeName)
1144                                + " on scope " + match,LOG_CHANNEL,Logger.INFO);
1145        }
1146        
1147    }
1148    
1149    /**
1150     *
1151     */
1152    private void notifyStoreCreated( String namespaceName, String scope, String storeName ) {
1153        
1154        if( createStoreListenerClass != null ) {
1155            try {
1156                Method nsc = createStoreListenerClass.getMethod(
1157                    "notifyStoreCreated", new Class[]{String.class, String.class, String.class} );
1158                nsc.invoke( null, new Object[]{namespaceName, scope, storeName} ); // obj=null since method is static
1159            }
1160            catch( Exception x ) {
1161                Domain.warn( "Notification of store creation "+
1162                                "(namespace="+namespaceName+", scope="+scope+", store="+storeName+") failed: "+x.getMessage() );
1163            }
1164        }
1165    }
1166    
1167    
1168    // --------------------------------------------------------- Object Methods
1169    
1170    
1171    /**
1172     * Get a String representation of this namespace.
1173     */
1174    public String toString() {
1175        return getName();
1176    }
1177    
1178    
1179}
1180