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: package org.apache.commons.configuration;
018:
019: import java.util.Hashtable;
020:
021: import javax.naming.Context;
022: import javax.naming.NameClassPair;
023: import javax.naming.NameNotFoundException;
024: import javax.naming.NamingEnumeration;
025: import javax.naming.NamingException;
026: import javax.naming.spi.InitialContextFactory;
027:
028: import com.mockobjects.dynamic.C;
029: import com.mockobjects.dynamic.Mock;
030:
031: /**
032: * A mock implementation of the <code>InitialContextFactory</code> interface.
033: * This implementation will return a mock context that contains some test data.
034: *
035: * @author <a
036: * href="http://jakarta.apache.org/commons/configuration/team-list.html">Commons
037: * Configuration team</a>
038: * @version $Id: MockInitialContextFactory.java 506128 2007-02-11 20:43:08Z oheger $
039: */
040: public class MockInitialContextFactory implements InitialContextFactory {
041: /** Constant for the lookup method. */
042: private static final String METHOD_LOOKUP = "lookup";
043:
044: /** Constant for the list method. */
045: private static final String METHOD_LIST = "list";
046:
047: /** Constant for the name of the missing property. */
048: private static final String MISSING_PROP = "/missing";
049:
050: /** Constant for the name of the prefix. */
051: private static final String PREFIX = "test/";
052:
053: /** An array with the names of the supported properties. */
054: private static final String[] PROP_NAMES = { "key", "key2",
055: "short", "boolean", "byte", "double", "float", "integer",
056: "long", "onlyinjndi" };
057:
058: /** An array with the values of the supported properties. */
059: private static final String[] PROP_VALUES = { "jndivalue",
060: "jndivalue2", "1", "true", "10", "10.25", "20.25", "10",
061: "1000000", "true" };
062:
063: /** An array with properties that are requested, but are not in the context. */
064: private static final String[] MISSING_NAMES = { "missing/list",
065: "test/imaginarykey", "foo/bar" };
066:
067: /**
068: * Creates a <code>Context</code> object that is backed by a mock object.
069: * The mock context can be queried for the values of certain test
070: * properties. It also supports listing the contained (sub) properties.
071: *
072: * @param env the environment
073: * @return the context mock
074: */
075: public Context getInitialContext(Hashtable env)
076: throws NamingException {
077: Mock mockTopCtx = createCtxMock(PREFIX);
078: Mock mockPrfxCtx = createCtxMock("");
079: Mock mockBaseCtx = new Mock(Context.class);
080: mockBaseCtx.matchAndReturn(METHOD_LOOKUP, C.eq(""), mockTopCtx
081: .proxy());
082: mockBaseCtx.matchAndReturn(METHOD_LOOKUP, C.eq("test"),
083: mockPrfxCtx.proxy());
084: mockTopCtx.matchAndReturn(METHOD_LOOKUP, C.eq("test"),
085: mockPrfxCtx.proxy());
086: mockTopCtx.matchAndReturn(METHOD_LIST, C.eq(""),
087: createEnumMock(mockTopCtx, new String[] { "test" },
088: new Object[] { mockPrfxCtx.proxy() }).proxy());
089: mockPrfxCtx.matchAndReturn(METHOD_LIST, C.eq(""),
090: createEnumMock(mockPrfxCtx, PROP_NAMES, PROP_VALUES)
091: .proxy());
092: return (Context) mockBaseCtx.proxy();
093: }
094:
095: /**
096: * Creates a mock for a Context with the specified prefix.
097: *
098: * @param prefix the prefix
099: * @return the mock for the context
100: */
101: private Mock createCtxMock(String prefix) {
102: Mock mockCtx = new Mock(Context.class);
103: for (int i = 0; i < PROP_NAMES.length; i++) {
104: bind(mockCtx, prefix + PROP_NAMES[i], PROP_VALUES[i]);
105: String errProp = (prefix.length() > 0) ? PROP_NAMES[i]
106: : PREFIX + PROP_NAMES[i];
107: bindError(mockCtx, errProp);
108: }
109: for (int i = 0; i < MISSING_NAMES.length; i++) {
110: bindError(mockCtx, MISSING_NAMES[i]);
111: }
112: return mockCtx;
113: }
114:
115: /**
116: * Binds a property value to the mock context.
117: *
118: * @param mockCtx the context
119: * @param name the name of the property
120: * @param value the value of the property
121: */
122: private void bind(Mock mockCtx, String name, String value) {
123: mockCtx.matchAndReturn(METHOD_LOOKUP, C.eq(name), value);
124: bindError(mockCtx, name + MISSING_PROP);
125: }
126:
127: /**
128: * Configures the mock to expect a call for a non existing property.
129: *
130: * @param mockCtx the mock
131: * @param name the name of the property
132: */
133: private void bindError(Mock mockCtx, String name) {
134: mockCtx.matchAndThrow(METHOD_LOOKUP, C.eq(name),
135: new NameNotFoundException("unknown property"));
136: }
137:
138: /**
139: * Creates and initializes a mock for a naming enumeration.
140: *
141: * @param mockCtx the mock representing the context
142: * @param names the names contained in the iteration
143: * @param values the corresponding values
144: * @return the mock for the enumeration
145: */
146: private Mock createEnumMock(Mock mockCtx, String[] names,
147: Object[] values) {
148: Mock mockEnum = new Mock(NamingEnumeration.class);
149: for (int i = 0; i < names.length; i++) {
150: NameClassPair ncp = new NameClassPair(names[i], values[i]
151: .getClass().getName());
152: mockEnum.expectAndReturn("hasMore", true);
153: mockEnum.expectAndReturn("next", ncp);
154: }
155: mockEnum.expectAndReturn("hasMore", false);
156: mockEnum.expect("close");
157: return mockEnum;
158: }
159: }
|