001: package org.mockejb.jndi;
002:
003: import java.util.*;
004:
005: import javax.naming.*;
006: import javax.naming.spi.InitialContextFactory;
007:
008: import org.mockejb.interceptor.InterceptableProxy;
009:
010: /**
011: * Creates {@link MockContext }. In case if delegate
012: * environment was provided, obtains delegate InitialContext.
013: * Delegate context is used by MockContext for unresolved lookups.
014: *
015: * @author Alexander Ananiev
016: * @author Dimitar Gospodinov
017: */
018: public class MockContextFactory implements InitialContextFactory {
019:
020: private static Map savedSystemProps = new HashMap();
021:
022: private static Hashtable delegateEnv;
023:
024: private static Context delegateContext;
025:
026: private static Context rootContext;
027:
028: /**
029: * Singleton for initial context.
030: * Instantiates and returns root/initial <code>MockContext</code> object that
031: * will be used as starting point for all naming operations.
032: * <code>MockContext</code> is then used by <code>javax.naming.InitialContext</code> object.
033: * It also creates the delegate context if the delegate environment is set. MockContextFactory
034: * caches the delegate context once it's created.
035: * @see javax.naming.spi.InitialContextFactory#getInitialContext(java.util.Hashtable)
036: * @return <code>MockContext</code> object
037: */
038: public Context getInitialContext(Hashtable environment)
039: throws NamingException {
040:
041: if (delegateContext == null && delegateEnv != null) {
042: delegateContext = new InitialContext(delegateEnv);
043: }
044:
045: if (rootContext == null) {
046: rootContext = (Context) InterceptableProxy.create(
047: Context.class, new MockContext(delegateContext));
048: }
049:
050: return rootContext;
051: }
052:
053: /**
054: * Sets the environment of the delegate JNDI context. Normally,
055: * this is the environment of the application server.
056: * At the very minimum, the environment includes PROVIDER_URL and INITIAL_CONTEXT_FACTORY.
057: * <code>MockContext</code> first tries to look up the object in its local tree.
058: * If the object is not found, it will look in the delegate context.
059: *
060: * @param env JNDI properties of the delegate environment
061: */
062: public static void setDelegateEnvironment(Hashtable env) {
063: delegateEnv = env;
064:
065: }
066:
067: /**
068: * Sets the delegate context. Normally,
069: * this is the initial context of the application server.
070: *
071: * <code>MockContext</code> first tries to look up the object in its local tree.
072: * If the object is not found, it will look in the delegate context.
073: *
074: * Example:
075: * <code>
076: * MockContextFactory.setDelegateContext( new InitialContext() );
077: * </code>
078: * @param ctx delegate context
079: */
080: public static void setDelegateContext(Context ctx) {
081: delegateContext = ctx;
082: }
083:
084: /**
085: * Sets the <code>MockContextFactory</code> as the initial context factory.
086: * This helper method sets the <code>Context.INITIAL_CONTEXT_FACTORY</code>
087: * and <code>Context.URL_PKG_PREFIXES</code> system properties. The second one is needed to
088: * be able to handle java:comp context correctly.
089: * The method also saves the current values of these properties so they can be
090: * restored later on using <code>revertSetAsInitial</code>.
091: * This method is normally called from <code>setUp</code>
092: * <p>
093: * You can also set these properties directly:
094: * <pre>
095: * <code>
096: * java.naming.factory.initial=org.mockejb.jndi.MockContextFactory
097: * java.naming.factory.url.pkgs=org.mockejb.jndi
098: * </code>
099: * <pre>
100: *
101: *
102: * @throws NamingException
103: */
104: public static void setAsInitial() throws NamingException {
105: // Preserve current set system props
106:
107: String key = Context.INITIAL_CONTEXT_FACTORY;
108: savedSystemProps.put(key, System.getProperty(key));
109:
110: key = Context.URL_PKG_PREFIXES;
111: savedSystemProps.put(key, System.getProperty(key));
112:
113: System.setProperty(Context.INITIAL_CONTEXT_FACTORY,
114: MockContextFactory.class.getName());
115: System
116: .setProperty(Context.URL_PKG_PREFIXES,
117: "org.mockejb.jndi");
118: }
119:
120: /**
121: * Restores the properties changed by <code>setAsInitial()</code>
122: * This method should be called in <code>tearDown()</code> to clean up
123: * all changes to the environment in case if the test is running in the app
124: * server.
125: * <p>
126: * This method also cleans the initial context.
127: */
128: public static void revertSetAsInitial() {
129: Iterator i = savedSystemProps.entrySet().iterator();
130: while (i.hasNext()) {
131: Map.Entry entry = (Map.Entry) i.next();
132: restoreSystemProperty((String) entry.getKey(),
133: (String) entry.getValue());
134: }
135:
136: rootContext = null;
137:
138: }
139:
140: private static void restoreSystemProperty(String key, String value) {
141:
142: if (value != null)
143: System.setProperty(key, value);
144: else
145: System.getProperties().remove(key);
146:
147: }
148:
149: }
|