001/* 002 * ModeShape (http://www.modeshape.org) 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.modeshape.common.naming; 017 018import java.util.Hashtable; 019import java.util.Map; 020import java.util.concurrent.ConcurrentHashMap; 021import javax.naming.Binding; 022import javax.naming.Context; 023import javax.naming.Name; 024import javax.naming.NameAlreadyBoundException; 025import javax.naming.NameClassPair; 026import javax.naming.NameNotFoundException; 027import javax.naming.NameParser; 028import javax.naming.NamingEnumeration; 029import javax.naming.NamingException; 030import javax.naming.spi.InitialContextFactory; 031import org.modeshape.common.SystemFailureException; 032 033/** 034 * A simple and limited {@link Context JNDI naming context} that can be used in unit tests for code that 035 * {@link Context#lookup(String) looks up} objects. 036 * <p> 037 * This can be used easily in a unit test by either using one of two methods. The first is using the convenient static 038 * <code>configure</code> method that takes one, two or three name/object pairs: 039 * 040 * <pre> 041 * SingletonInitialContext.register(name, obj); 042 * SingletonInitialContext.register(name1, obj1, name2, obj2); 043 * SingletonInitialContext.register(name1, obj1, name2, obj2, name3, obj3); 044 * </pre> 045 * 046 * </p> 047 * <p> 048 * The other approach is to set the system property for the {@link InitialContextFactory}: 049 * 050 * <pre> 051 * System.setProperty("java.naming.factory.initial", "org.modeshape.common.mock.SingletonInitialContextFactory"); 052 * </pre> 053 * 054 * and then to {@link Context#bind(String, Object) bind} an object. 055 * 056 * @see SingletonInitialContextFactory 057 * @author Luca Stancapiano 058 * @author Randall Hauch 059 */ 060public class SingletonInitialContext implements Context { 061 062 /** 063 * A convenience method that registers the supplied object with the supplied name. 064 * 065 * @param name the JNDI name 066 * @param obj the object to be registered 067 */ 068 public static void register( String name, 069 Object obj ) { 070 register(name, obj, null, null, null, null); 071 } 072 073 /** 074 * A convenience method that registers the supplied objects with the supplied names. 075 * 076 * @param name1 the JNDI name for the first object 077 * @param obj1 the first object to be registered 078 * @param name2 the JNDI name for the second object 079 * @param obj2 the second object to be registered 080 */ 081 public static void register( String name1, 082 Object obj1, 083 String name2, 084 Object obj2 ) { 085 register(name1, obj1, name2, obj2, null, null); 086 } 087 088 /** 089 * A convenience method that registers the supplied objects with the supplied names. 090 * 091 * @param name1 the JNDI name for the first object 092 * @param obj1 the first object to be registered 093 * @param name2 the JNDI name for the second object 094 * @param obj2 the second object to be registered 095 * @param name3 the JNDI name for the third object 096 * @param obj3 the third object to be registered 097 */ 098 public static void register( String name1, 099 Object obj1, 100 String name2, 101 Object obj2, 102 String name3, 103 Object obj3 ) { 104 SingletonInitialContextFactory.initialize(); 105 try { 106 javax.naming.InitialContext context = new javax.naming.InitialContext(); 107 if (name1 != null) context.rebind(name1, obj1); 108 if (name2 != null) context.rebind(name2, obj2); 109 if (name3 != null) context.rebind(name3, obj3); 110 } catch (NamingException e) { 111 throw new SystemFailureException("Unable to create the mock InitialContext", e); 112 } 113 } 114 115 private final Map<String, Object> environment = new ConcurrentHashMap<String, Object>(); 116 private final ConcurrentHashMap<String, Object> registry = new ConcurrentHashMap<String, Object>(); 117 118 /* package */SingletonInitialContext( Hashtable<?, ?> environment ) { 119 if (environment != null) { 120 for (Map.Entry<?, ?> entry : environment.entrySet()) { 121 this.environment.put(entry.getKey().toString(), entry.getValue()); 122 } 123 } 124 } 125 126 @Override 127 public Object addToEnvironment( String propName, 128 Object propVal ) { 129 return environment.put(propName, propVal); 130 } 131 132 @Override 133 public Object removeFromEnvironment( String propName ) { 134 return environment.remove(propName); 135 } 136 137 @Override 138 public void bind( Name name, 139 Object obj ) throws NamingException { 140 bind(name.toString(), obj); 141 } 142 143 @Override 144 public void bind( String name, 145 Object obj ) throws NamingException { 146 if (this.registry.putIfAbsent(name, obj) != null) { 147 throw new NameAlreadyBoundException("The name \"" + name + "\" is already bound to an object"); 148 } 149 } 150 151 @Override 152 public void rebind( Name name, 153 Object obj ) { 154 rebind(name.toString(), obj); 155 } 156 157 @Override 158 public void rebind( String name, 159 Object obj ) { 160 this.registry.put(name, obj); 161 } 162 163 @Override 164 public void unbind( String name ) { 165 this.registry.remove(name); 166 } 167 168 @Override 169 public void unbind( Name name ) { 170 unbind(name.toString()); 171 } 172 173 @Override 174 public Object lookup( Name name ) throws NamingException { 175 return lookup(name.toString()); 176 } 177 178 @Override 179 public Object lookup( String name ) throws NamingException { 180 Object result = this.registry.get(name); 181 if (result == null) { 182 throw new NameNotFoundException("No object is registered at \"" + name + "\""); 183 } 184 return result; 185 } 186 187 @Override 188 public Object lookupLink( String name ) { 189 throw new UnsupportedOperationException(); 190 } 191 192 @Override 193 public Object lookupLink( Name name ) { 194 throw new UnsupportedOperationException(); 195 } 196 197 @Override 198 public void rename( Name oldName, 199 Name newName ) { 200 throw new UnsupportedOperationException(); 201 } 202 203 @Override 204 public void rename( String oldName, 205 String newName ) { 206 throw new UnsupportedOperationException(); 207 } 208 209 @Override 210 public void close() { 211 } 212 213 @Override 214 public Name composeName( Name name, 215 Name prefix ) { 216 throw new UnsupportedOperationException(); 217 } 218 219 @Override 220 public String composeName( String name, 221 String prefix ) { 222 throw new UnsupportedOperationException(); 223 } 224 225 @Override 226 public Context createSubcontext( Name name ) { 227 throw new UnsupportedOperationException(); 228 } 229 230 @Override 231 public Context createSubcontext( String name ) { 232 throw new UnsupportedOperationException(); 233 } 234 235 @Override 236 public void destroySubcontext( Name name ) { 237 throw new UnsupportedOperationException(); 238 } 239 240 @Override 241 public void destroySubcontext( String name ) { 242 throw new UnsupportedOperationException(); 243 } 244 245 @Override 246 public Hashtable<?, ?> getEnvironment() { 247 Hashtable<String, String> hashtable = new Hashtable<String, String>(); 248 Map<?, ?> map = this.environment; 249 for (Map.Entry<?, ?> dd : map.entrySet()) { 250 hashtable.put(dd.getKey().toString(), dd.getValue().toString()); 251 } 252 return hashtable; 253 } 254 255 @Override 256 public String getNameInNamespace() { 257 throw new UnsupportedOperationException(); 258 } 259 260 @Override 261 public NameParser getNameParser( Name name ) { 262 throw new UnsupportedOperationException(); 263 } 264 265 @Override 266 public NameParser getNameParser( String name ) { 267 throw new UnsupportedOperationException(); 268 } 269 270 @Override 271 public NamingEnumeration<NameClassPair> list( Name name ) { 272 throw new UnsupportedOperationException(); 273 } 274 275 @Override 276 public NamingEnumeration<NameClassPair> list( String name ) { 277 throw new UnsupportedOperationException(); 278 } 279 280 @Override 281 public NamingEnumeration<Binding> listBindings( Name name ) { 282 throw new UnsupportedOperationException(); 283 } 284 285 @Override 286 public NamingEnumeration<Binding> listBindings( String name ) { 287 throw new UnsupportedOperationException(); 288 } 289}