1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.configuration;
19  
20  import junit.framework.TestCase;
21  
22  import javax.naming.Context;
23  import javax.naming.InitialContext;
24  import javax.naming.NamingException;
25  
26  import org.apache.commons.configuration.event.ConfigurationErrorEvent;
27  import org.apache.commons.configuration.event.ConfigurationErrorListener;
28  
29  /***
30   * Test to see if the JNDIConfiguration works properly.
31   *
32   * @version $Id: TestJNDIConfiguration.java 506128 2007-02-11 20:43:08Z oheger $
33   */
34  public class TestJNDIConfiguration extends TestCase {
35  
36      public static final String CONTEXT_FACTORY = MockInitialContextFactory.class.getName();
37  
38      private JNDIConfiguration conf;
39      private NonStringTestHolder nonStringTestHolder;
40  
41      /*** A test error listener for counting internal errors.*/
42      private TestErrorListener listener;
43  
44      public void setUp() throws Exception {
45  
46          System.setProperty("java.naming.factory.initial", CONTEXT_FACTORY);
47  
48          conf = new PotentialErrorJNDIConfiguration();
49  
50          nonStringTestHolder = new NonStringTestHolder();
51          nonStringTestHolder.setConfiguration(conf);
52  
53          listener = new TestErrorListener();
54          conf.addErrorListener(listener);
55      }
56  
57      /***
58       * Clears the test environment. If an error listener is defined, checks
59       * whether no error event was received.
60       */
61      protected void tearDown() throws Exception
62      {
63          if (listener != null)
64          {
65              listener.verify();
66          }
67          super.tearDown();
68      }
69  
70      public void testBoolean() throws Exception {
71          nonStringTestHolder.testBoolean();
72      }
73  
74      public void testBooleanDefaultValue() throws Exception {
75          nonStringTestHolder.testBooleanDefaultValue();
76      }
77  
78      public void testByte() throws Exception {
79          nonStringTestHolder.testByte();
80      }
81  
82      public void testDouble() throws Exception {
83          nonStringTestHolder.testDouble();
84      }
85  
86      public void testDoubleDefaultValue() throws Exception {
87          nonStringTestHolder.testDoubleDefaultValue();
88      }
89  
90      public void testFloat() throws Exception {
91          nonStringTestHolder.testFloat();
92      }
93  
94      public void testFloatDefaultValue() throws Exception {
95          nonStringTestHolder.testFloatDefaultValue();
96      }
97  
98      public void testInteger() throws Exception {
99          nonStringTestHolder.testInteger();
100     }
101 
102     public void testIntegerDefaultValue() throws Exception {
103         nonStringTestHolder.testIntegerDefaultValue();
104     }
105 
106     public void testLong() throws Exception {
107         nonStringTestHolder.testLong();
108     }
109 
110     public void testLongDefaultValue() throws Exception {
111         nonStringTestHolder.testLongDefaultValue();
112     }
113 
114     public void testShort() throws Exception {
115         nonStringTestHolder.testShort();
116     }
117 
118     public void testShortDefaultValue() throws Exception {
119         nonStringTestHolder.testShortDefaultValue();
120     }
121 
122     public void testListMissing() throws Exception {
123         nonStringTestHolder.testListMissing();
124     }
125 
126     public void testSubset() throws Exception {
127         nonStringTestHolder.testSubset();
128     }
129 
130     public void testProperties() throws Exception {
131         Object o = conf.getProperty("test.boolean");
132         assertNotNull(o);
133         assertEquals("true", o.toString());
134     }
135 
136     public void testContainsKey()
137     {
138         String key = "test.boolean";
139         assertTrue("'" + key + "' not found", conf.containsKey(key));
140 
141         conf.clearProperty(key);
142         assertFalse("'" + key + "' still found", conf.containsKey(key));
143     }
144 
145     public void testChangePrefix()
146     {
147         assertEquals("'test.boolean' property", "true", conf.getString("test.boolean"));
148         assertEquals("'boolean' property", null, conf.getString("boolean"));
149 
150         // change the prefix
151         conf.setPrefix("test");
152         assertEquals("'test.boolean' property", null, conf.getString("test.boolean"));
153         assertEquals("'boolean' property", "true", conf.getString("boolean"));
154     }
155 
156     public void testResetRemovedProperties() throws Exception
157     {
158         assertEquals("'test.boolean' property", "true", conf.getString("test.boolean"));
159 
160         // remove the property
161         conf.clearProperty("test.boolean");
162         assertEquals("'test.boolean' property", null, conf.getString("test.boolean"));
163 
164         // change the context
165         conf.setContext(new InitialContext());
166 
167         // get the property
168         assertEquals("'test.boolean' property", "true", conf.getString("test.boolean"));
169     }
170 
171     public void testConstructor() throws Exception
172     {
173         // test the constructor accepting a context
174         conf = new JNDIConfiguration(new InitialContext());
175 
176         assertEquals("'test.boolean' property", "true", conf.getString("test.boolean"));
177 
178         // test the constructor accepting a context and a prefix
179         conf = new JNDIConfiguration(new InitialContext(), "test");
180 
181         assertEquals("'boolean' property", "true", conf.getString("boolean"));
182     }
183 
184     /***
185      * Configures the test config to throw an exception.
186      */
187     private PotentialErrorJNDIConfiguration setUpErrorConfig()
188     {
189         ((PotentialErrorJNDIConfiguration) conf).failOnGetCtx = true;
190         conf.removeErrorListener((ConfigurationErrorListener) conf
191                 .getErrorListeners().iterator().next());
192         return (PotentialErrorJNDIConfiguration) conf;
193     }
194 
195     /***
196      * Tests whether the expected error events have been received.
197      *
198      * @param type the expected event type
199      * @param propName the name of the property
200      * @param propValue the property value
201      */
202     private void checkErrorListener(int type, String propName, Object propValue)
203     {
204         listener.verify(type, propName, propValue);
205         listener = null;
206     }
207 
208     /***
209      * Tests whether a JNDI configuration registers an error log listener.
210      */
211     public void testLogListener() throws NamingException
212     {
213         conf = new JNDIConfiguration();
214         assertEquals("No error log listener registered", 1, conf
215                 .getErrorListeners().size());
216     }
217 
218     /***
219      * Tests handling of errors in getKeys().
220      */
221     public void testGetKeysError()
222     {
223         assertFalse("Iteration not empty", setUpErrorConfig().getKeys()
224                 .hasNext());
225         checkErrorListener(AbstractConfiguration.EVENT_READ_PROPERTY, null,
226                 null);
227     }
228 
229     /***
230      * Tests handling of errors in isEmpty().
231      */
232     public void testIsEmptyError() throws NamingException
233     {
234         assertTrue("Error config not empty", setUpErrorConfig().isEmpty());
235         checkErrorListener(AbstractConfiguration.EVENT_READ_PROPERTY, null,
236                 null);
237     }
238 
239     /***
240      * Tests handling of errors in the containsKey() method.
241      */
242     public void testContainsKeyError()
243     {
244         assertFalse("Key contained after error", setUpErrorConfig()
245                 .containsKey("key"));
246         checkErrorListener(AbstractConfiguration.EVENT_READ_PROPERTY, "key",
247                 null);
248     }
249 
250     /***
251      * Tests handling of errors in getProperty().
252      */
253     public void testGetPropertyError()
254     {
255         assertNull("Wrong property value after error", setUpErrorConfig()
256                 .getProperty("key"));
257         checkErrorListener(AbstractConfiguration.EVENT_READ_PROPERTY, "key",
258                 null);
259     }
260 
261     /***
262      * A special JNDI configuration implementation that can be configured to
263      * throw an exception when accessing the base context. Used for testing the
264      * exception handling.
265      */
266     static class PotentialErrorJNDIConfiguration extends JNDIConfiguration
267     {
268         /*** A flag whether an exception should be thrown. */
269         boolean failOnGetCtx;
270 
271         public PotentialErrorJNDIConfiguration() throws NamingException
272         {
273             super();
274         }
275 
276         public Context getBaseContext() throws NamingException
277         {
278             if (failOnGetCtx)
279             {
280                 throw new NamingException("Simulated JNDI exception!");
281             }
282             return super.getBaseContext();
283         }
284     }
285 
286     /***
287      * A test listener implementation that is used for counting and testing
288      * internal errors.
289      */
290     static class TestErrorListener implements ConfigurationErrorListener
291     {
292         /*** Stores the last received error event. */
293         ConfigurationErrorEvent event;
294 
295         /*** Stores the number of calls. */
296         int errorCount;
297 
298         public void configurationError(ConfigurationErrorEvent event)
299         {
300             this.event = event;
301             errorCount++;
302         }
303 
304         /***
305          * Checks whether no error event was received.
306          */
307         public void verify()
308         {
309             assertEquals("Error events received", 0, errorCount);
310         }
311 
312         /***
313          * Checks whether an expected error event was received.
314          *
315          * @param type the type of the event
316          * @param propName the name of the property
317          * @param propValue the value of the property
318          */
319         public void verify(int type, String propName, Object propValue)
320         {
321             assertEquals("Wrong number of error events", 1, errorCount);
322             assertEquals("Wrong event type", type, event.getType());
323             assertTrue("Wrong property name", (propName == null) ? event
324                     .getPropertyName() == null : propName.equals(event
325                     .getPropertyName()));
326             assertTrue("Wrong property value", (propValue == null) ? event
327                     .getPropertyValue() == null : propValue.equals(event
328                     .getPropertyValue()));
329             assertTrue("Wrong exception class",
330                     event.getCause() instanceof NamingException);
331         }
332     }
333 }