KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > sape > carbon > services > config > jndi > JNDIFolder


1 /*
2  * The contents of this file are subject to the Sapient Public License
3  * Version 1.0 (the "License"); you may not use this file except in compliance
4  * with the License. You may obtain a copy of the License at
5  * http://carbon.sf.net/License.html.
6  *
7  * Software distributed under the License is distributed on an "AS IS" basis,
8  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
9  * the specific language governing rights and limitations under the License.
10  *
11  * The Original Code is The Carbon Component Framework.
12  *
13  * The Initial Developer of the Original Code is Sapient Corporation
14  *
15  * Copyright (C) 2003 Sapient Corporation. All Rights Reserved.
16  */

17
18 package org.sape.carbon.services.config.jndi;
19
20 import java.util.HashSet JavaDoc;
21 import java.util.Set JavaDoc;
22
23 import javax.naming.Name JavaDoc;
24 import javax.naming.NamingEnumeration JavaDoc;
25 import javax.naming.NamingException JavaDoc;
26 import javax.naming.directory.Attributes JavaDoc;
27 import javax.naming.directory.DirContext JavaDoc;
28 import javax.naming.directory.SearchControls JavaDoc;
29 import javax.naming.directory.SearchResult JavaDoc;
30 import javax.naming.event.EventContext JavaDoc;
31 import javax.naming.event.NamespaceChangeListener JavaDoc;
32 import javax.naming.event.NamingEvent JavaDoc;
33 import javax.naming.event.NamingExceptionEvent JavaDoc;
34 import javax.naming.event.ObjectChangeListener JavaDoc;
35
36 import org.sape.carbon.core.config.InvalidConfigurationException;
37 import org.sape.carbon.core.config.format.ConfigurationFormatException;
38 import org.sape.carbon.core.config.format.DefaultConfigurationFormatService;
39 import org.sape.carbon.core.config.node.AbstractFolder;
40 import org.sape.carbon.core.config.node.ConfigurationDocument;
41 import org.sape.carbon.core.config.node.Node;
42 import org.sape.carbon.core.config.node.NodeCreationException;
43 import org.sape.carbon.core.config.node.NodeFactory;
44 import org.sape.carbon.core.config.node.NodeIOException;
45 import org.sape.carbon.core.config.node.NodeNotFoundException;
46 import org.sape.carbon.core.config.node.NodeRemovalException;
47 import org.sape.carbon.core.config.node.link.LinkNodeConfiguration;
48 import org.sape.carbon.core.config.node.link.LinkNodeFactory;
49 import org.sape.carbon.core.exception.ExceptionUtility;
50 import org.sape.carbon.core.exception.InvalidParameterException;
51
52 import org.apache.commons.logging.Log;
53 import org.apache.commons.logging.LogFactory;
54
55 /**
56  * A node that represents a JNDI context that contains other folders or documents.
57  * This implementation implements NamespaceChangeListener and
58  * ObjectChangeListener from the javax.naming.event package in order to listen
59  * for changes in the backing datastore.
60  *
61  * Copyright 2003 Sapient
62  * @since carbon 2.0
63  * @author Douglas Voet, March 2003
64  * @version $Revision: 1.12 $($Author: dvoet $ / $Date: 2003/07/29 18:52:33 $)
65  */

66 public class JNDIFolder
67     extends AbstractFolder
68     implements NamespaceChangeListener JavaDoc, ObjectChangeListener JavaDoc {
69
70     private Log log = LogFactory.getLog(this.getClass());
71
72     /** Filter string used in getAllChildNames to get folders and documents names */
73     private static final String JavaDoc SUBCONTEXT_FILTER = "(|({0}={1})({0}={2}))";
74
75     private DirContext JavaDoc initialContext;
76     private Name JavaDoc nodeContextName;
77     private JNDILinkNodeConfiguration config;
78
79     /**
80      * Constructs the JNDIFolder and registers itself as a
81      * JNDI naming listener
82      *
83      * @param parent the parent node of this node
84      * @param name the name of this node
85      * @param subFolderFactory factory used to create sub folders
86      * @param configurationDocumentFactory factory used to create sub documents
87      * @param linkNodeFactory factory used to create sub links
88      * @param initialContext the jndi initial context
89      * @param nodeContextName the name of this node's context
90      * @param config configuration used to get the names of the attributes
91      * that hold node name, node and document type, and document content as well
92      * as valid attribute values for node and document type.
93      */

94     protected JNDIFolder(
95         Node parent,
96         String JavaDoc name,
97         NodeFactory subFolderFactory,
98         NodeFactory configurationDocumentFactory,
99         NodeFactory linkNodeFactory,
100         DirContext JavaDoc initialContext,
101         Name JavaDoc nodeContextName,
102         JNDILinkNodeConfiguration config) {
103
104         super(
105             parent,
106             name,
107             subFolderFactory,
108             configurationDocumentFactory,
109             linkNodeFactory);
110
111         // validate parameters
112
if (initialContext == null) {
113             throw new InvalidParameterException(
114                 this.getClass(),
115                 "initialContext cannot be null in node ["
116                     + getAbsoluteName()
117                     + "]");
118         }
119         if (nodeContextName == null) {
120             throw new InvalidParameterException(
121                 this.getClass(),
122                 "nodeContextName cannot be null in node ["
123                     + getAbsoluteName()
124                     + "]");
125         }
126         if (config == null) {
127             throw new InvalidParameterException(
128                 this.getClass(),
129                 "config cannot be null in node ["
130                     + getAbsoluteName()
131                     + "]");
132         }
133
134         this.initialContext = initialContext;
135         this.nodeContextName = nodeContextName;
136         this.config = config;
137
138         // register for JNDI events for this context
139
registerNamingListener();
140     }
141
142     /**
143      * @inherit
144      */

145     protected Set JavaDoc getAllChildNames() {
146         Set JavaDoc childNameSet = new HashSet JavaDoc();
147
148         try {
149             // get the name attribute of all immediate sub contexts of
150
// either document or folder type
151

152             // the values of subcontextFilterArgs are plugged into
153
// SUBCONTEXT_FILTER
154
Object JavaDoc[] subcontextFilterArgs = new Object JavaDoc[] {
155                 this.config.getNodeTypeAttributeName(),
156                 this.config.getFolderNodeTypeAttributeValue(),
157                 this.config.getDocumentNodeTypeAttributeValue()
158             };
159
160             // specify only the name attribute to return
161
SearchControls JavaDoc subcontextSearchControls = new SearchControls JavaDoc();
162             subcontextSearchControls.setReturningAttributes(
163                 new String JavaDoc[] { this.config.getNodeNameAttributeName() });
164
165             NamingEnumeration JavaDoc childrenEnum =
166                 this.initialContext.search(
167                     nodeContextName,
168                     JNDIFolder.SUBCONTEXT_FILTER,
169                     subcontextFilterArgs,
170                     subcontextSearchControls);
171
172             // add the name of each sub context to childNameSet
173
while (childrenEnum.hasMoreElements()) {
174                 SearchResult JavaDoc result = (SearchResult JavaDoc) childrenEnum.nextElement();
175                 childNameSet.add(
176                     result
177                         .getAttributes()
178                         .get(this.config.getNodeNameAttributeName())
179                         .get());
180             }
181
182         } catch (NamingException JavaDoc ne) {
183             if (log.isInfoEnabled()) {
184                 log.info("Could not get names of children, reason: "
185                         + ExceptionUtility.printStackTracesToString(ne));
186             }
187         }
188
189         return childNameSet;
190     }
191
192     /**
193      * @inherit
194      */

195     protected Node loadChild(String JavaDoc nodeName) throws NodeNotFoundException {
196
197         // these constants are defined in order to make the code below readable
198
final String JavaDoc NAME = this.config.getNodeNameAttributeName();
199         final String JavaDoc EQUALS = this.config.getAttributeNameValueSeparator();
200         final String JavaDoc NODE_TYPE = this.config.getNodeTypeAttributeName();
201         final String JavaDoc FOLDER = this.config.getFolderNodeTypeAttributeValue();
202         final String JavaDoc DOCUMENT = this.config.getDocumentNodeTypeAttributeValue();
203         final String JavaDoc DOC_TYPE = this.config.getDocumentTypeAttributeName();
204         final String JavaDoc LINK = this.config.getLinkDocumentTypeAttributeValue();
205         final String JavaDoc CONTENT = this.config.getDocumentDocumentTypeAttributeValue();
206
207         try {
208             // create the child context name
209
Name JavaDoc childContextName = (Name JavaDoc) this.nodeContextName.clone();
210             childContextName.add(NAME + EQUALS + nodeName);
211
212             String JavaDoc[] docuemntAttributeIDs = new String JavaDoc[] {
213                 this.config.getNodeTypeAttributeName(),
214                 this.config.getDocumentTypeAttributeName()
215             };
216
217             // get the child's attributes
218
Attributes JavaDoc attributes = this.initialContext.getAttributes(
219                 childContextName,
220                 docuemntAttributeIDs);
221
222             // figure out what kind of node it is and load it
223
if (attributes.get(NODE_TYPE) != null) {
224                 if (attributes.get(NODE_TYPE).contains(FOLDER)) {
225                     return loadSubFolder(nodeName);
226                 }
227
228                 if (attributes.get(DOC_TYPE) != null &&
229                     attributes.get(NODE_TYPE).contains(DOCUMENT)) {
230
231                     if (attributes.get(DOC_TYPE).contains(LINK)) {
232                         return loadChildLinkNode(nodeName);
233                     }
234
235                     if (attributes.get(DOC_TYPE).contains(CONTENT)) {
236                         return loadConfigurationDocument(nodeName);
237                     }
238                 }
239             }
240
241             // requried attributes were not found or
242
// did not match a folder, document, or link
243
throw new NodeNotFoundException(
244                 this.getClass(),
245                 this.getAbsoluteName() + Node.DELIMITER + nodeName);
246
247         } catch (NodeCreationException nce) {
248             throw new NodeNotFoundException(this.getClass(), nodeName, nce);
249
250         } catch (NamingException JavaDoc ne) {
251             throw new NodeNotFoundException(this.getClass(), nodeName, ne);
252         }
253     }
254
255     /**
256      * Calls destroySubcontext with this context's name
257      * @throws NodeRemovalException if a NamingException is encountered
258      */

259     protected void destroyBackingData() throws NodeRemovalException {
260         try {
261             this.initialContext.destroySubcontext(this.nodeContextName);
262         } catch (NamingException JavaDoc ne) {
263             throw new NodeRemovalException(this.getClass(), this, ne);
264         }
265     }
266
267     /**
268      * Gets this nodes initial context. Used by JNDI node factories
269      * to pass onto child nodes
270      * @return DirContext
271      */

272     DirContext JavaDoc getInitialContext() {
273         return this.initialContext;
274     }
275
276     /**
277      * Gets this nodes context name. Used by JNDI node factories
278      * to construct child node context names
279      * @return Name
280      */

281     Name JavaDoc getNodeContextName() {
282         return this.nodeContextName;
283     }
284
285     /**
286      * Helper method to create a sub folder
287      *
288      * @param nodeName
289      * @return Node
290      * @throws NodeCreationException
291      */

292     private Node loadSubFolder(String JavaDoc nodeName) throws NodeCreationException {
293         return getSubFolderFactory().getInstance(this, nodeName);
294     }
295
296     /**
297      * Helper method to create a configuration document
298      *
299      * @param nodeName
300      * @return Node
301      * @throws NodeCreationException
302      */

303     private Node loadConfigurationDocument(String JavaDoc nodeName)
304         throws NodeCreationException {
305
306         return getConfigurationDocumentFactory().getInstance(this, nodeName);
307     }
308
309     /**
310      * Helper method to create a sub link
311      *
312      * @param nodeName
313      * @return Node
314      * @throws NodeCreationException
315      */

316     private Node loadChildLinkNode(String JavaDoc nodeName)
317         throws NodeCreationException {
318
319         // these constants are defined in order to make the code below readable
320
final String JavaDoc NAME = this.config.getNodeNameAttributeName();
321         final String JavaDoc EQUALS = this.config.getAttributeNameValueSeparator();
322         final String JavaDoc LINK = this.config.getLinkDocumentTypeAttributeValue();
323
324         try {
325             // load the link configuration
326
Name JavaDoc childContextName = (Name JavaDoc) this.nodeContextName.clone();
327             childContextName.add(NAME + EQUALS + nodeName);
328
329             ConfigurationDocument linkConfiguraitonDoc =
330                 new JNDIConfigurationDocument(
331                     this,
332                     nodeName,
333                     new DefaultConfigurationFormatService(),
334                     this.initialContext,
335                     childContextName,
336                     this.config,
337                     LINK);
338
339             LinkNodeConfiguration config =
340                 (LinkNodeConfiguration) linkConfiguraitonDoc
341                     .readConfiguration();
342
343             if (config.getLinkNodeFactoryClass() == null) {
344                 throw new InvalidConfigurationException(
345                     this.getClass(),
346                     config.getConfigurationName(),
347                     "LinkNodeFactoryClass",
348                     "Cannot be null");
349             }
350
351             // get the LinkNodeFactory from the configuration
352
LinkNodeFactory factory =
353                 (LinkNodeFactory) config
354                     .getLinkNodeFactoryClass()
355                     .newInstance();
356
357             // use the factory to get a link node instance
358
return factory.getInstance(this, nodeName, linkConfiguraitonDoc);
359
360         } catch (ConfigurationFormatException e) {
361             throw new NodeCreationException(
362                 this.getClass(), this, nodeName, "exception occured", e);
363         } catch (NodeIOException e) {
364             throw new NodeCreationException(
365                 this.getClass(), this, nodeName, "exception occured", e);
366         } catch (InstantiationException JavaDoc e) {
367             throw new NodeCreationException(
368                 this.getClass(), this, nodeName, "exception occured", e);
369         } catch (IllegalAccessException JavaDoc e) {
370             throw new NodeCreationException(
371                 this.getClass(), this, nodeName, "exception occured", e);
372         } catch (NamingException JavaDoc ne) {
373             throw new NodeCreationException(
374                 this.getClass(), this, nodeName, "NamingException occured", ne);
375         }
376     }
377
378     /**
379      * Checks the backing directory to see if this nodes context exists and
380      * if it does, has the right attributes.
381      */

382     protected boolean backingDataExists() {
383         final String JavaDoc NODE_TYPE = this.config.getNodeTypeAttributeName();
384         final String JavaDoc FOLDER = this.config.getFolderNodeTypeAttributeValue();
385
386         boolean backingDataExists;
387         try {
388             Attributes JavaDoc folderAttributes =
389                 this.initialContext.getAttributes(this.nodeContextName);
390
391             if (folderAttributes.get(NODE_TYPE) != null &&
392                 folderAttributes.get(NODE_TYPE).contains(FOLDER)) {
393
394                 backingDataExists = true;
395             } else {
396                 backingDataExists = false;
397             }
398         } catch (NamingException JavaDoc ne) {
399             backingDataExists = false;
400         }
401
402         return backingDataExists;
403     }
404
405     /**
406      * This implementation does not do anything if an object is added
407      * because the child could not have been loaded yet could not be cached
408      */

409     public void objectAdded(NamingEvent JavaDoc evt) {
410         // don't care
411
}
412
413     /**
414      * Causes a refresh of this node
415      */

416     public void objectRemoved(NamingEvent JavaDoc evt) {
417         refresh();
418     }
419
420     /**
421      * Causes a refresh of this node
422      */

423     public void objectRenamed(NamingEvent JavaDoc evt) {
424         refresh();
425     }
426
427     /**
428      * Causes a refresh of this node
429      */

430     public void objectChanged(NamingEvent JavaDoc evt) {
431         refresh();
432     }
433
434     /**
435      * Logs the fact that a NamingExceptionEvent occured
436      */

437     public void namingExceptionThrown(NamingExceptionEvent JavaDoc evt) {
438         if (log.isInfoEnabled()) {
439             log.info("Notified of NamingExceptionEvent, this node is no "
440                 + "longer listening for JNDI events, node name: ["
441                 + getAbsoluteName()
442                 + "], context name: ["
443                 + this.nodeContextName
444                 + "] naming exception: "
445                 + ExceptionUtility.printStackTracesToString(evt.getException()));
446         }
447     }
448
449     /**
450      * Registers this node as a NamingListener with the backing context
451      */

452     protected void registerNamingListener() {
453         try {
454             // get the event context
455
EventContext JavaDoc thisContext = (EventContext JavaDoc)
456                 this.initialContext.lookup(this.nodeContextName);
457
458             // register for changes in object scope (this context only)
459
thisContext.addNamingListener("", EventContext.OBJECT_SCOPE, this);
460
461         } catch (ClassCastException JavaDoc cce) {
462             if (log.isInfoEnabled()) {
463                 log.info(
464                     "Node was not registered as a JNDI NamingListener because "
465                         + "events were not supported by directory, node: ["
466                         + getAbsoluteName()
467                         + "], context name: ["
468                         + this.nodeContextName
469                         + "]");
470             }
471         } catch (NamingException JavaDoc ne) {
472             if (log.isInfoEnabled()) {
473                 log.info(
474                     "NamingException caught registering NamingListener, node: ["
475                         + getAbsoluteName()
476                         + "], context name: ["
477                         + this.nodeContextName
478                         + "]",
479                     ne);
480             }
481         }
482     }
483 }
Popular Tags