001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.commons.configuration; 019 020 import static org.junit.Assert.assertEquals; 021 import static org.junit.Assert.assertFalse; 022 import static org.junit.Assert.assertNotNull; 023 import static org.junit.Assert.assertNull; 024 import static org.junit.Assert.assertTrue; 025 026 import java.util.Hashtable; 027 import java.util.Properties; 028 029 import javax.naming.Context; 030 import javax.naming.InitialContext; 031 import javax.naming.NameNotFoundException; 032 import javax.naming.NamingException; 033 034 import org.junit.After; 035 import org.junit.Before; 036 import org.junit.Test; 037 038 /** 039 * Test to see if the JNDIConfiguration works properly. 040 * 041 * @version $Id: TestJNDIConfiguration.java 1301996 2012-03-17 20:30:39Z sebb $ 042 */ 043 public class TestJNDIConfiguration { 044 045 public static final String CONTEXT_FACTORY = MockInitialContextFactory.class.getName(); 046 047 private PotentialErrorJNDIConfiguration conf; 048 private NonStringTestHolder nonStringTestHolder; 049 050 /** A test error listener for counting internal errors.*/ 051 private ConfigurationErrorListenerImpl listener; 052 053 @Before 054 public void setUp() throws Exception { 055 056 System.setProperty("java.naming.factory.initial", CONTEXT_FACTORY); 057 058 Properties props = new Properties(); 059 props.put("java.naming.factory.initial", CONTEXT_FACTORY); 060 Context ctx = new InitialContext(props); 061 conf = new PotentialErrorJNDIConfiguration(ctx); 062 063 nonStringTestHolder = new NonStringTestHolder(); 064 nonStringTestHolder.setConfiguration(conf); 065 066 listener = new ConfigurationErrorListenerImpl(); 067 conf.addErrorListener(listener); 068 } 069 070 /** 071 * Clears the test environment. If an error listener is defined, checks 072 * whether no error event was received. 073 */ 074 @After 075 public void tearDown() throws Exception 076 { 077 if (listener != null) 078 { 079 listener.verify(); 080 } 081 } 082 083 @Test 084 public void testBoolean() throws Exception { 085 nonStringTestHolder.testBoolean(); 086 } 087 088 @Test 089 public void testBooleanDefaultValue() throws Exception { 090 nonStringTestHolder.testBooleanDefaultValue(); 091 } 092 093 @Test 094 public void testByte() throws Exception { 095 nonStringTestHolder.testByte(); 096 } 097 098 @Test 099 public void testDouble() throws Exception { 100 nonStringTestHolder.testDouble(); 101 } 102 103 @Test 104 public void testDoubleDefaultValue() throws Exception { 105 nonStringTestHolder.testDoubleDefaultValue(); 106 } 107 108 @Test 109 public void testFloat() throws Exception { 110 nonStringTestHolder.testFloat(); 111 } 112 113 @Test 114 public void testFloatDefaultValue() throws Exception { 115 nonStringTestHolder.testFloatDefaultValue(); 116 } 117 118 @Test 119 public void testInteger() throws Exception { 120 nonStringTestHolder.testInteger(); 121 } 122 123 @Test 124 public void testIntegerDefaultValue() throws Exception { 125 nonStringTestHolder.testIntegerDefaultValue(); 126 } 127 128 @Test 129 public void testLong() throws Exception { 130 nonStringTestHolder.testLong(); 131 } 132 133 @Test 134 public void testLongDefaultValue() throws Exception { 135 nonStringTestHolder.testLongDefaultValue(); 136 } 137 138 @Test 139 public void testShort() throws Exception { 140 nonStringTestHolder.testShort(); 141 } 142 143 @Test 144 public void testShortDefaultValue() throws Exception { 145 nonStringTestHolder.testShortDefaultValue(); 146 } 147 148 @Test 149 public void testListMissing() throws Exception { 150 nonStringTestHolder.testListMissing(); 151 } 152 153 @Test 154 public void testSubset() throws Exception { 155 nonStringTestHolder.testSubset(); 156 } 157 158 @Test 159 public void testProperties() throws Exception { 160 Object o = conf.getProperty("test.boolean"); 161 assertNotNull(o); 162 assertEquals("true", o.toString()); 163 } 164 165 @Test 166 public void testContainsKey() 167 { 168 String key = "test.boolean"; 169 assertTrue("'" + key + "' not found", conf.containsKey(key)); 170 171 conf.clearProperty(key); 172 assertFalse("'" + key + "' still found", conf.containsKey(key)); 173 } 174 175 @Test 176 public void testChangePrefix() 177 { 178 assertEquals("'test.boolean' property", "true", conf.getString("test.boolean")); 179 assertEquals("'boolean' property", null, conf.getString("boolean")); 180 181 // change the prefix 182 conf.setPrefix("test"); 183 assertEquals("'test.boolean' property", null, conf.getString("test.boolean")); 184 assertEquals("'boolean' property", "true", conf.getString("boolean")); 185 } 186 187 @Test 188 public void testResetRemovedProperties() throws Exception 189 { 190 assertEquals("'test.boolean' property", "true", conf.getString("test.boolean")); 191 192 // remove the property 193 conf.clearProperty("test.boolean"); 194 assertEquals("'test.boolean' property", null, conf.getString("test.boolean")); 195 196 // change the context 197 conf.setContext(new InitialContext()); 198 199 // get the property 200 assertEquals("'test.boolean' property", "true", conf.getString("test.boolean")); 201 } 202 203 @Test 204 public void testConstructor() throws Exception 205 { 206 // test the constructor accepting a context 207 JNDIConfiguration c = new JNDIConfiguration(new InitialContext()); 208 209 assertEquals("'test.boolean' property", "true", c.getString("test.boolean")); 210 211 // test the constructor accepting a context and a prefix 212 c = new JNDIConfiguration(new InitialContext(), "test"); 213 214 assertEquals("'boolean' property", "true", c.getString("boolean")); 215 } 216 217 /** 218 * Configures the test config to throw an exception. 219 */ 220 private PotentialErrorJNDIConfiguration setUpErrorConfig() 221 { 222 conf.installException(); 223 conf.removeErrorListener(conf.getErrorListeners().iterator().next()); 224 return conf; 225 } 226 227 /** 228 * Tests whether the expected error events have been received. 229 * 230 * @param type the expected event type 231 * @param propName the name of the property 232 * @param propValue the property value 233 */ 234 private void checkErrorListener(int type, String propName, Object propValue) 235 { 236 listener.verify(type, propName, propValue); 237 assertTrue("Wrong exception class", 238 listener.getLastEvent().getCause() instanceof NamingException); 239 listener = null; 240 } 241 242 /** 243 * Tests whether a JNDI configuration registers an error log listener. 244 */ 245 @Test 246 public void testLogListener() throws NamingException 247 { 248 JNDIConfiguration c = new JNDIConfiguration(); 249 assertEquals("No error log listener registered", 1, c 250 .getErrorListeners().size()); 251 } 252 253 /** 254 * Tests handling of errors in getKeys(). 255 */ 256 @Test 257 public void testGetKeysError() 258 { 259 assertFalse("Iteration not empty", setUpErrorConfig().getKeys() 260 .hasNext()); 261 checkErrorListener(AbstractConfiguration.EVENT_READ_PROPERTY, null, 262 null); 263 } 264 265 /** 266 * Tests handling of errors in isEmpty(). 267 */ 268 @Test 269 public void testIsEmptyError() throws Exception 270 { 271 assertTrue("Error config not empty", setUpErrorConfig().isEmpty()); 272 checkErrorListener(AbstractConfiguration.EVENT_READ_PROPERTY, null, 273 null); 274 } 275 276 /** 277 * Tests handling of errors in the containsKey() method. 278 */ 279 @Test 280 public void testContainsKeyError() 281 { 282 assertFalse("Key contained after error", setUpErrorConfig() 283 .containsKey("key")); 284 checkErrorListener(AbstractConfiguration.EVENT_READ_PROPERTY, "key", 285 null); 286 } 287 288 /** 289 * Tests handling of errors in getProperty(). 290 */ 291 @Test 292 public void testGetPropertyError() 293 { 294 assertNull("Wrong property value after error", setUpErrorConfig() 295 .getProperty("key")); 296 checkErrorListener(AbstractConfiguration.EVENT_READ_PROPERTY, "key", 297 null); 298 } 299 300 /** 301 * Tests the getKeys() method when there are cycles in the tree. 302 */ 303 @Test 304 public void testGetKeysWithCycles() throws NamingException 305 { 306 Hashtable<Object, Object> env = new Hashtable<Object, Object>(); 307 env.put(MockInitialContextFactory.PROP_CYCLES, Boolean.TRUE); 308 InitialContext initCtx = new InitialContext(env); 309 JNDIConfiguration c = new JNDIConfiguration(initCtx); 310 c.getKeys("cycle"); 311 } 312 313 /** 314 * Tests getKeys() if no data is found. This should not cause a problem and 315 * not notify the error listeners. 316 */ 317 @Test 318 public void testGetKeysNoData() 319 { 320 conf.installException(new NameNotFoundException("Test exception")); 321 assertFalse("Got keys", conf.getKeys().hasNext()); 322 listener.verify(); 323 } 324 325 /** 326 * A special JNDI configuration implementation that can be configured to 327 * throw an exception when accessing the base context. Used for testing the 328 * exception handling. 329 */ 330 public static class PotentialErrorJNDIConfiguration extends 331 JNDIConfiguration 332 { 333 /** An exception to be thrown by getBaseContext(). */ 334 private NamingException exception; 335 336 public PotentialErrorJNDIConfiguration(Context ctx) 337 throws NamingException 338 { 339 super(ctx); 340 } 341 342 /** 343 * Prepares this object to throw an exception when the JNDI context is 344 * queried. 345 * 346 * @param nex the exception to be thrown 347 */ 348 public void installException(NamingException nex) 349 { 350 exception = nex; 351 } 352 353 /** 354 * Prepares this object to throw a standard exception when the JNDI 355 * context is queried. 356 */ 357 public void installException() 358 { 359 installException(new NamingException("Simulated JNDI exception!")); 360 } 361 362 /** 363 * Returns the JNDI context. Optionally throws an exception. 364 */ 365 @Override 366 public Context getBaseContext() throws NamingException 367 { 368 if (exception != null) 369 { 370 throw exception; 371 } 372 return super.getBaseContext(); 373 } 374 } 375 }