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
9
* http://www.apache.org/licenses/LICENSE-2.0
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.
17
package org.apache.commons.configuration;
19
import java.util.Hashtable;
21
import javax.naming.Context;
22
import javax.naming.NameClassPair;
23
import javax.naming.NameNotFoundException;
24
import javax.naming.NamingEnumeration;
25
import javax.naming.NamingException;
26
import javax.naming.spi.InitialContextFactory;
28
import com.mockobjects.dynamic.C;
29
import com.mockobjects.dynamic.Mock;
32
* A mock implementation of the <code>InitialContextFactory</code> interface.
33
* This implementation will return a mock context that contains some test data.
36
* href="http://commons.apache.org/configuration/team-list.html">Commons
37
* Configuration team</a>
38
* @version $Id: MockInitialContextFactory.java 561230 2007-07-31 04:17:09Z rahul $
40
public class MockInitialContextFactory implements InitialContextFactory
43
* Constant for the use cycles environment property. If this property is
44
* present in the environment, a cyclic context will be created.
46
public static final String PROP_CYCLES = "useCycles";
48
/** Constant for the lookup method. */
49
private static final String METHOD_LOOKUP = "lookup";
51
/** Constant for the list method. */
52
private static final String METHOD_LIST = "list";
54
/** Constant for the close method.*/
55
private static final String METHOD_CLOSE = "close";
57
/** Constant for the name of the missing property. */
58
private static final String MISSING_PROP = "/missing";
60
/** Constant for the name of the prefix. */
61
private static final String PREFIX = "test/";
63
/** An array with the names of the supported properties. */
64
private static final String[] PROP_NAMES =
65
{ "key", "key2", "short", "boolean", "byte", "double", "float", "integer",
66
"long", "onlyinjndi" };
68
/** An array with the values of the supported properties. */
69
private static final String[] PROP_VALUES =
70
{ "jndivalue", "jndivalue2", "1", "true", "10", "10.25", "20.25", "10",
73
/** An array with properties that are requested, but are not in the context. */
74
private static final String[] MISSING_NAMES =
75
{ "missing/list", "test/imaginarykey", "foo/bar" };
78
* Creates a <code>Context</code> object that is backed by a mock object.
79
* The mock context can be queried for the values of certain test
80
* properties. It also supports listing the contained (sub) properties.
82
* @param env the environment
83
* @return the context mock
85
public Context getInitialContext(Hashtable env) throws NamingException
87
boolean useCycles = env.containsKey(PROP_CYCLES);
89
Mock mockTopCtx = createCtxMock(PREFIX);
90
Mock mockCycleCtx = createCtxMock("");
91
Mock mockPrfxCtx = createCtxMock("");
92
Mock mockBaseCtx = new Mock(Context.class);
93
mockBaseCtx.matchAndReturn(METHOD_LOOKUP, C.eq(""), mockTopCtx.proxy());
94
mockBaseCtx.matchAndReturn(METHOD_LOOKUP, C.eq("test"), mockPrfxCtx
96
mockTopCtx.matchAndReturn(METHOD_LOOKUP, C.eq("test"), mockPrfxCtx
98
mockPrfxCtx.matchAndReturn(METHOD_LIST, C.eq(""), createEnumMock(
99
mockPrfxCtx, PROP_NAMES, PROP_VALUES).proxy());
103
mockTopCtx.matchAndReturn(METHOD_LOOKUP, C.eq("cycle"),
104
mockCycleCtx.proxy());
105
mockTopCtx.matchAndReturn(METHOD_LIST, C.eq(""), createEnumMock(
106
mockTopCtx, new String[]
107
{ "test", "cycle" }, new Object[]
108
{ mockPrfxCtx.proxy(), mockCycleCtx.proxy() }).proxy());
109
Mock mockEnum = createEnumMock(mockCycleCtx, PROP_NAMES,
111
addEnumPair(mockEnum, "cycleCtx", mockCycleCtx.proxy());
114
.matchAndReturn(METHOD_LIST, C.eq(""), mockEnum.proxy());
115
mockCycleCtx.matchAndReturn(METHOD_LOOKUP, C.eq("cycleCtx"),
116
mockCycleCtx.proxy());
120
mockTopCtx.matchAndReturn(METHOD_LIST, C.eq(""), createEnumMock(
121
mockTopCtx, new String[]
122
{ "test" }, new Object[]
123
{ mockPrfxCtx.proxy() }).proxy());
125
return (Context) mockBaseCtx.proxy();
129
* Creates a mock for a Context with the specified prefix.
131
* @param prefix the prefix
132
* @return the mock for the context
134
private Mock createCtxMock(String prefix)
136
Mock mockCtx = new Mock(Context.class);
137
for (int i = 0; i < PROP_NAMES.length; i++)
139
bind(mockCtx, prefix + PROP_NAMES[i], PROP_VALUES[i]);
140
String errProp = (prefix.length() > 0) ? PROP_NAMES[i] : PREFIX
142
bindError(mockCtx, errProp);
144
for (int i = 0; i < MISSING_NAMES.length; i++)
146
bindError(mockCtx, MISSING_NAMES[i]);
148
mockCtx.matchAndReturn("hashCode", System.identityHashCode(mockCtx.proxy()));
154
* Binds a property value to the mock context.
156
* @param mockCtx the context
157
* @param name the name of the property
158
* @param value the value of the property
160
private void bind(Mock mockCtx, String name, String value)
162
mockCtx.matchAndReturn(METHOD_LOOKUP, C.eq(name), value);
163
bindError(mockCtx, name + MISSING_PROP);
167
* Configures the mock to expect a call for a non existing property.
169
* @param mockCtx the mock
170
* @param name the name of the property
172
private void bindError(Mock mockCtx, String name)
174
mockCtx.matchAndThrow(METHOD_LOOKUP, C.eq(name),
175
new NameNotFoundException("unknown property"));
179
* Creates and initializes a mock for a naming enumeration.
181
* @param mockCtx the mock representing the context
182
* @param names the names contained in the iteration
183
* @param values the corresponding values
184
* @param close a flag whether the enumeration should expect to be closed
185
* @return the mock for the enumeration
187
private Mock createEnumMock(Mock mockCtx, String[] names, Object[] values,
190
Mock mockEnum = new Mock(NamingEnumeration.class);
191
for (int i = 0; i < names.length; i++)
193
addEnumPair(mockEnum, names[i], values[i]);
203
* Creates and initializes a mock for a naming enumeration that expects to
204
* be closed. This is a shortcut of createEnumMock(mockCtx, names, values,
207
* @param mockCtx the mock representing the context
208
* @param names the names contained in the iteration
209
* @param values the corresponding values
210
* @return the mock for the enumeration
212
private Mock createEnumMock(Mock mockCtx, String[] names, Object[] values)
214
return createEnumMock(mockCtx, names, values, true);
218
* Adds a new name-and-value pair to an enum mock.
220
* @param mockEnum the enum mock
221
* @param name the name
222
* @param value the value
224
private void addEnumPair(Mock mockEnum, String name, Object value)
226
NameClassPair ncp = new NameClassPair(name, value.getClass().getName());
227
mockEnum.expectAndReturn("hasMore", true);
228
mockEnum.expectAndReturn("next", ncp);
232
* Closes an enumeration mock.
234
* @param mockEnum the mock
236
private void closeEnum(Mock mockEnum)
238
mockEnum.expectAndReturn("hasMore", false);
239
mockEnum.expect(METHOD_CLOSE);