| MockContextFactory.java |
package org.mockejb.jndi;
import java.util.*;
import javax.naming.*;
import javax.naming.spi.InitialContextFactory;
import org.mockejb.interceptor.InterceptableProxy;
/**
* Creates {@link MockContext }. In case if delegate
* environment was provided, obtains delegate InitialContext.
* Delegate context is used by MockContext for unresolved lookups.
*
* @author Alexander Ananiev
* @author Dimitar Gospodinov
*/
public class MockContextFactory implements InitialContextFactory {
private static Map savedSystemProps = new HashMap();
private static Hashtable delegateEnv;
private static Context delegateContext;
private static Context rootContext;
/**
* Singleton for initial context.
* Instantiates and returns root/initial <code>MockContext</code> object that
* will be used as starting point for all naming operations.
* <code>MockContext</code> is then used by <code>javax.naming.InitialContext</code> object.
* It also creates the delegate context if the delegate environment is set. MockContextFactory
* caches the delegate context once it's created.
* @see javax.naming.spi.InitialContextFactory#getInitialContext(java.util.Hashtable)
* @return <code>MockContext</code> object
*/
public Context getInitialContext(Hashtable environment) throws NamingException {
if ( delegateContext == null && delegateEnv != null ) {
delegateContext = new InitialContext( delegateEnv );
}
if ( rootContext == null) {
rootContext = (Context) InterceptableProxy.create(
Context.class, new MockContext(delegateContext) );
}
return rootContext;
}
/**
* Sets the environment of the delegate JNDI context. Normally,
* this is the environment of the application server.
* At the very minimum, the environment includes PROVIDER_URL and INITIAL_CONTEXT_FACTORY.
* <code>MockContext</code> first tries to look up the object in its local tree.
* If the object is not found, it will look in the delegate context.
*
* @param env JNDI properties of the delegate environment
*/
public static void setDelegateEnvironment( Hashtable env ) {
delegateEnv = env;
}
/**
* Sets the delegate context. Normally,
* this is the initial context of the application server.
*
* <code>MockContext</code> first tries to look up the object in its local tree.
* If the object is not found, it will look in the delegate context.
*
* Example:
* <code>
* MockContextFactory.setDelegateContext( new InitialContext() );
* </code>
* @param ctx delegate context
*/
public static void setDelegateContext( Context ctx ) {
delegateContext = ctx;
}
/**
* Sets the <code>MockContextFactory</code> as the initial context factory.
* This helper method sets the <code>Context.INITIAL_CONTEXT_FACTORY</code>
* and <code>Context.URL_PKG_PREFIXES</code> system properties. The second one is needed to
* be able to handle java:comp context correctly.
* The method also saves the current values of these properties so they can be
* restored later on using <code>revertSetAsInitial</code>.
* This method is normally called from <code>setUp</code>
* <p>
* You can also set these properties directly:
* <pre>
* <code>
* java.naming.factory.initial=org.mockejb.jndi.MockContextFactory
* java.naming.factory.url.pkgs=org.mockejb.jndi
* </code>
* <pre>
*
*
* @throws NamingException
*/
public static void setAsInitial() throws NamingException {
// Preserve current set system props
String key = Context.INITIAL_CONTEXT_FACTORY;
savedSystemProps.put( key, System.getProperty( key ) );
key = Context.URL_PKG_PREFIXES;
savedSystemProps.put( key, System.getProperty( key ) );
System.setProperty( Context.INITIAL_CONTEXT_FACTORY, MockContextFactory.class.getName() );
System.setProperty( Context.URL_PKG_PREFIXES, "org.mockejb.jndi" );
}
/**
* Restores the properties changed by <code>setAsInitial()</code>
* This method should be called in <code>tearDown()</code> to clean up
* all changes to the environment in case if the test is running in the app
* server.
* <p>
* This method also cleans the initial context.
*/
public static void revertSetAsInitial() {
Iterator i = savedSystemProps.entrySet().iterator();
while( i.hasNext( ) ){
Map.Entry entry = (Map.Entry) i.next();
restoreSystemProperty( (String)entry.getKey(), (String)entry.getValue() );
}
rootContext = null;
}
private static void restoreSystemProperty( String key, String value ){
if ( value != null )
System.setProperty( key, value );
else
System.getProperties().remove( key );
}
}