/*
* ModeShape (http://www.modeshape.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.modeshape.common.naming;
import java.util.Hashtable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.naming.Binding;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.NameAlreadyBoundException;
import javax.naming.NameClassPair;
import javax.naming.NameNotFoundException;
import javax.naming.NameParser;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.spi.InitialContextFactory;
import org.modeshape.common.SystemFailureException;
/**
* A simple and limited {@link Context JNDI naming context} that can be used in unit tests for code that
* {@link Context#lookup(String) looks up} objects.
* <p>
* This can be used easily in a unit test by either using one of two methods. The first is using the convenient static
* <code>configure</code> method that takes one, two or three name/object pairs:
*
* <pre>
* SingletonInitialContext.register(name, obj);
* SingletonInitialContext.register(name1, obj1, name2, obj2);
* SingletonInitialContext.register(name1, obj1, name2, obj2, name3, obj3);
* </pre>
*
* </p>
* <p>
* The other approach is to set the system property for the {@link InitialContextFactory}:
*
* <pre>
* System.setProperty("java.naming.factory.initial", "org.modeshape.common.mock.SingletonInitialContextFactory");
* </pre>
*
* and then to {@link Context#bind(String, Object) bind} an object.
*
* @see SingletonInitialContextFactory
* @author Luca Stancapiano
* @author Randall Hauch
*/
public class SingletonInitialContext implements Context {
/**
* A convenience method that registers the supplied object with the supplied name.
*
* @param name the JNDI name
* @param obj the object to be registered
*/
public static void register( String name,
Object obj ) {
register(name, obj, null, null, null, null);
}
/**
* A convenience method that registers the supplied objects with the supplied names.
*
* @param name1 the JNDI name for the first object
* @param obj1 the first object to be registered
* @param name2 the JNDI name for the second object
* @param obj2 the second object to be registered
*/
public static void register( String name1,
Object obj1,
String name2,
Object obj2 ) {
register(name1, obj1, name2, obj2, null, null);
}
/**
* A convenience method that registers the supplied objects with the supplied names.
*
* @param name1 the JNDI name for the first object
* @param obj1 the first object to be registered
* @param name2 the JNDI name for the second object
* @param obj2 the second object to be registered
* @param name3 the JNDI name for the third object
* @param obj3 the third object to be registered
*/
public static void register( String name1,
Object obj1,
String name2,
Object obj2,
String name3,
Object obj3 ) {
SingletonInitialContextFactory.initialize();
try {
javax.naming.InitialContext context = new javax.naming.InitialContext();
if (name1 != null) context.rebind(name1, obj1);
if (name2 != null) context.rebind(name2, obj2);
if (name3 != null) context.rebind(name3, obj3);
} catch (NamingException e) {
throw new SystemFailureException("Unable to create the mock InitialContext", e);
}
}
private final Map<String, Object> environment = new ConcurrentHashMap<String, Object>();
private final ConcurrentHashMap<String, Object> registry = new ConcurrentHashMap<String, Object>();
/* package */SingletonInitialContext( Hashtable<?, ?> environment ) {
if (environment != null) {
for (Map.Entry<?, ?> entry : environment.entrySet()) {
this.environment.put(entry.getKey().toString(), entry.getValue());
}
}
}
@Override
public Object addToEnvironment( String propName,
Object propVal ) {
return environment.put(propName, propVal);
}
@Override
public Object removeFromEnvironment( String propName ) {
return environment.remove(propName);
}
@Override
public void bind( Name name,
Object obj ) throws NamingException {
bind(name.toString(), obj);
}
@Override
public void bind( String name,
Object obj ) throws NamingException {
if (this.registry.putIfAbsent(name, obj) != null) {
throw new NameAlreadyBoundException("The name \"" + name + "\" is already bound to an object");
}
}
@Override
public void rebind( Name name,
Object obj ) {
rebind(name.toString(), obj);
}
@Override
public void rebind( String name,
Object obj ) {
this.registry.put(name, obj);
}
@Override
public void unbind( String name ) {
this.registry.remove(name);
}
@Override
public void unbind( Name name ) {
unbind(name.toString());
}
@Override
public Object lookup( Name name ) throws NamingException {
return lookup(name.toString());
}
@Override
public Object lookup( String name ) throws NamingException {
Object result = this.registry.get(name);
if (result == null) {
throw new NameNotFoundException("No object is registered at \"" + name + "\"");
}
return result;
}
@Override
public Object lookupLink( String name ) {
throw new UnsupportedOperationException();
}
@Override
public Object lookupLink( Name name ) {
throw new UnsupportedOperationException();
}
@Override
public void rename( Name oldName,
Name newName ) {
throw new UnsupportedOperationException();
}
@Override
public void rename( String oldName,
String newName ) {
throw new UnsupportedOperationException();
}
@Override
public void close() {
}
@Override
public Name composeName( Name name,
Name prefix ) {
throw new UnsupportedOperationException();
}
@Override
public String composeName( String name,
String prefix ) {
throw new UnsupportedOperationException();
}
@Override
public Context createSubcontext( Name name ) {
throw new UnsupportedOperationException();
}
@Override
public Context createSubcontext( String name ) {
throw new UnsupportedOperationException();
}
@Override
public void destroySubcontext( Name name ) {
throw new UnsupportedOperationException();
}
@Override
public void destroySubcontext( String name ) {
throw new UnsupportedOperationException();
}
@Override
public Hashtable<?, ?> getEnvironment() {
Hashtable<String, String> hashtable = new Hashtable<String, String>();
Map<?, ?> map = this.environment;
for (Map.Entry<?, ?> dd : map.entrySet()) {
hashtable.put(dd.getKey().toString(), dd.getValue().toString());
}
return hashtable;
}
@Override
public String getNameInNamespace() {
throw new UnsupportedOperationException();
}
@Override
public NameParser getNameParser( Name name ) {
throw new UnsupportedOperationException();
}
@Override
public NameParser getNameParser( String name ) {
throw new UnsupportedOperationException();
}
@Override
public NamingEnumeration<NameClassPair> list( Name name ) {
throw new UnsupportedOperationException();
}
@Override
public NamingEnumeration<NameClassPair> list( String name ) {
throw new UnsupportedOperationException();
}
@Override
public NamingEnumeration<Binding> listBindings( Name name ) {
throw new UnsupportedOperationException();
}
@Override
public NamingEnumeration<Binding> listBindings( String name ) {
throw new UnsupportedOperationException();
}
}