KickJava   Java API By Example, From Geeks To Geeks.

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


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.io.ByteArrayInputStream JavaDoc;
21 import java.io.ByteArrayOutputStream JavaDoc;
22 import java.io.InputStream JavaDoc;
23 import java.io.OutputStream JavaDoc;
24
25 import javax.naming.Name JavaDoc;
26 import javax.naming.NameNotFoundException JavaDoc;
27 import javax.naming.NamingException JavaDoc;
28 import javax.naming.directory.Attribute JavaDoc;
29 import javax.naming.directory.Attributes JavaDoc;
30 import javax.naming.directory.BasicAttributes JavaDoc;
31 import javax.naming.directory.DirContext JavaDoc;
32 import javax.naming.event.EventContext JavaDoc;
33 import javax.naming.event.NamespaceChangeListener JavaDoc;
34 import javax.naming.event.NamingEvent JavaDoc;
35 import javax.naming.event.NamingExceptionEvent JavaDoc;
36 import javax.naming.event.ObjectChangeListener JavaDoc;
37
38 import org.sape.carbon.core.config.InvalidConfigurationException;
39 import org.sape.carbon.core.config.format.ConfigurationFormatService;
40 import org.sape.carbon.core.config.node.AbstractConfigurationDocument;
41 import org.sape.carbon.core.config.node.Node;
42 import org.sape.carbon.core.config.node.NodeRemovalException;
43 import org.sape.carbon.core.exception.ExceptionUtility;
44 import org.sape.carbon.core.exception.InvalidParameterException;
45
46 import org.apache.commons.logging.Log;
47 import org.apache.commons.logging.LogFactory;
48
49 /**
50  * A node that represents a JNDI context that contains content.
51  * Content is read and writen using a <code>ConfigurationFormatService</code>.
52  * This implementation implements NamespaceChangeListener and
53  * ObjectChangeListener from the javax.naming.event package in order to listen
54  * for changes in the backing datastore.
55  *
56  * Copyright 2003 Sapient
57  * @since carbon 2.0
58  * @author Douglas Voet, March 2003
59  * @version $Revision: 1.11 $($Author: dvoet $ / $Date: 2003/05/05 21:21:10 $)
60  */

61 public class JNDIConfigurationDocument
62     extends AbstractConfigurationDocument
63     implements NamespaceChangeListener JavaDoc, ObjectChangeListener JavaDoc {
64
65     private Log log = LogFactory.getLog(this.getClass());
66
67     private DirContext JavaDoc initialContext;
68     private Name JavaDoc nodeContextName;
69     private JNDILinkNodeConfiguration config;
70     private String JavaDoc documentType;
71
72     /**
73      * Constructs the JNDIConfigurationDocument and registers itself as a
74      * JNDI naming listener
75      *
76      * @param parent the parent node of this node
77      * @param name the name of this node
78      * @param formatter the format service this node should use
79      * @param initialContext the jndi initial context
80      * @param nodeContextName the name of this node's context
81      * @param config configuration used to get the names of the attributes
82      * that hold node name, node and document type, and document content as well
83      * as valid attribute values for node and document type.
84      */

85     public JNDIConfigurationDocument(
86         Node parent,
87         String JavaDoc name,
88         ConfigurationFormatService formatter,
89         DirContext JavaDoc initialContext,
90         Name JavaDoc nodeContextName,
91         JNDILinkNodeConfiguration config,
92         String JavaDoc documentType) {
93
94         super(parent, name, formatter);
95
96         // validate parameters
97
if (initialContext == null) {
98             throw new InvalidParameterException(
99                 this.getClass(),
100                 "initialContext cannot be null in node ["
101                 + getAbsoluteName()
102                 + "]");
103         }
104         if (nodeContextName == null) {
105             throw new InvalidParameterException(
106                 this.getClass(),
107                 "nodeContextName cannot be null in node ["
108                 + getAbsoluteName()
109                 + "]");
110         }
111         if (config == null) {
112             throw new InvalidParameterException(
113                 this.getClass(),
114                 "config cannot be null in node ["
115                 + getAbsoluteName()
116                 + "]");
117         }
118         if (documentType == null) {
119             throw new InvalidParameterException(
120                 this.getClass(),
121                 "documentType cannot be null in node ["
122                 + getAbsoluteName()
123                 + "]");
124         }
125
126         this.initialContext = initialContext;
127         this.nodeContextName = nodeContextName;
128         this.config = config;
129         this.documentType = documentType;
130
131         // register for JNDI events for this context
132
registerNamingListener();
133     }
134
135     /**
136      * Calls destroySubcontext with this context's name
137      * @throws NodeRemovalException if a NamingException is encountered
138      */

139     protected void destroyBackingData() throws NodeRemovalException {
140         try {
141             this.initialContext.destroySubcontext(this.nodeContextName);
142         } catch (NamingException JavaDoc ne) {
143             throw new NodeRemovalException(this.getClass(), this, ne);
144         }
145     }
146
147     /**
148      * Gets the content from the JNDI directory and converts it to a stream
149      *
150      * @throws NamingException if content cannot be read from the jndi directory
151      * @throws InvalidConfigurationException if there is no content in this
152      * nodes context
153      */

154     protected InputStream JavaDoc openInputStream() throws NamingException JavaDoc {
155         String JavaDoc[] contentAttirbuteIDs = new String JavaDoc[]{
156             this.config.getDocumentContectAttributeName()
157         };
158
159         // get the document's content attribute
160
Attributes JavaDoc documentAttributes =
161             this.initialContext.getAttributes(
162                 this.nodeContextName,
163                 contentAttirbuteIDs);
164
165         Attribute JavaDoc contentAttribute =
166             documentAttributes.get(config.getDocumentContectAttributeName());
167
168         if (contentAttribute == null || contentAttribute.get() == null) {
169             throw new InvalidConfigurationException(
170                 this.getClass(),
171                 getAbsoluteName(),
172                 "",
173                 "content was missing from JNDI context: ["
174                 + this.nodeContextName.toString()
175                 + "]");
176         }
177
178         // get the actual content and convert create a ByteArrayInputStream
179
String JavaDoc content = (String JavaDoc) contentAttribute.get();
180         return new ByteArrayInputStream JavaDoc(content.getBytes());
181     }
182
183     /**
184      * Returns a new ByteArrayOutputStream that is read when it is closed
185      */

186     protected OutputStream JavaDoc openOutputStream() {
187         return new ByteArrayOutputStream JavaDoc();
188     }
189
190     /**
191      * Gets the data from the output stream and writes it to the jndi directory
192      * @throws NamingException if there is a problem writing to the directory
193      */

194     protected void closeOutputStream(OutputStream JavaDoc out) throws Exception JavaDoc {
195         ByteArrayOutputStream JavaDoc outputStream = (ByteArrayOutputStream JavaDoc) out;
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 NODE_TYPE = this.config.getNodeTypeAttributeName();
200         final String JavaDoc DOCUMENT = this.config.getDocumentNodeTypeAttributeValue();
201         final String JavaDoc DOC_TYPE = this.config.getDocumentTypeAttributeName();
202         final String JavaDoc CONTENT = this.config.getDocumentContectAttributeName();
203
204         try {
205             // Replace the content of the backing context with the string value
206
// of the ByteArrayOutputStream
207
this.initialContext.modifyAttributes(
208                 this.nodeContextName,
209                 DirContext.REPLACE_ATTRIBUTE,
210                 new BasicAttributes JavaDoc(CONTENT, outputStream.toString()));
211
212         } catch (NameNotFoundException JavaDoc nnfe) {
213             // the name was not found, so create it
214
if (log.isTraceEnabled()) {
215                 log.trace("Creating new context [" + this.nodeContextName + "]");
216             }
217
218             Attributes JavaDoc docAttributes = new BasicAttributes JavaDoc();
219             docAttributes.put(NAME, getName());
220             docAttributes.put(NODE_TYPE, DOCUMENT);
221             docAttributes.put(DOC_TYPE, this.documentType);
222             docAttributes.put(CONTENT, outputStream.toString());
223
224             initialContext.createSubcontext(nodeContextName, docAttributes);
225
226             registerNamingListener();
227         }
228
229
230         super.closeOutputStream(out);
231     }
232
233     /**
234      * Checks the backing directory to see if this nodes context exists and
235      * if it does, has the right attributes.
236      */

237     protected boolean backingDataExists() {
238         final String JavaDoc NODE_TYPE = this.config.getNodeTypeAttributeName();
239         final String JavaDoc DOCUMENT = this.config.getDocumentNodeTypeAttributeValue();
240
241         boolean backingDataExists;
242         try {
243             Attributes JavaDoc documentAttributes =
244                 this.initialContext.getAttributes(this.nodeContextName);
245             if (documentAttributes.get(NODE_TYPE) != null &&
246                 documentAttributes.get(NODE_TYPE).contains(DOCUMENT)) {
247
248                 backingDataExists = true;
249             } else {
250                 backingDataExists = false;
251             }
252         } catch (NamingException JavaDoc ne) {
253             backingDataExists = false;
254         }
255
256         return backingDataExists;
257     }
258
259     /**
260      * This implementation does not do anything if an object is added.
261      */

262     public void objectAdded(NamingEvent JavaDoc evt) {
263         // don't care
264
}
265
266     /**
267      * Causes a refresh of this node
268      */

269     public void objectRemoved(NamingEvent JavaDoc evt) {
270         if (log.isTraceEnabled()) {
271             log.trace("Caught objectRemoved naming event on node [" +
272                 getAbsoluteName() + "]");
273         }
274         refresh();
275     }
276
277     /**
278      * Causes a refresh of this node
279      */

280     public void objectRenamed(NamingEvent JavaDoc evt) {
281         if (log.isTraceEnabled()) {
282             log.trace("Caught objectRenamed naming event on node [" +
283                 getAbsoluteName() + "]");
284         }
285         refresh();
286     }
287
288     /**
289      * Causes a refresh of this node
290      */

291     public void objectChanged(NamingEvent JavaDoc evt) {
292         if (log.isTraceEnabled()) {
293             log.trace("Caught objectChanged naming event on node [" +
294                 getAbsoluteName() + "]");
295         }
296         refresh();
297     }
298
299     /**
300      * Logs the fact that a NamingExceptionEvent occured
301      */

302     public void namingExceptionThrown(NamingExceptionEvent JavaDoc evt) {
303         if (log.isInfoEnabled()) {
304             log.info("Notified of NamingExceptionEvent, this node is no "
305                 + "longer listening for JNDI events, node name: ["
306                 + getAbsoluteName()
307                 + "], context name: ["
308                 + this.nodeContextName
309                 + "], naming exception: "
310                 + ExceptionUtility.printStackTracesToString(evt.getException()));
311         }
312     }
313
314     /**
315      * Registers this node as a NamingListener with the backing context
316      */

317     protected void registerNamingListener() {
318         try {
319             // get the event context
320
EventContext JavaDoc thisContext = (EventContext JavaDoc)
321                 this.initialContext.lookup(this.nodeContextName);
322
323             // register for changes in object scope (this context only)
324
thisContext.addNamingListener("", EventContext.OBJECT_SCOPE, this);
325
326         } catch (ClassCastException JavaDoc cce) {
327             if (log.isInfoEnabled()) {
328                 log.info(
329                     "Node was not registered as a JNDI NamingListener because "
330                     + "events were not supported by directory, node: ["
331                     + getAbsoluteName()
332                     + "], context name: ["
333                     + this.nodeContextName
334                     + "]");
335             }
336         } catch (NamingException JavaDoc ne) {
337             if (log.isDebugEnabled()) {
338                 log.debug(
339                     "NamingException caught registering NamingListener, node: ["
340                     + getAbsoluteName()
341                     + "], context name: ["
342                     + this.nodeContextName
343                     + "]",
344                     ne);
345             }
346         }
347     }
348 }
Popular Tags