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 */ 017package org.apache.wicket.spring.test; 018 019import java.io.IOException; 020import java.io.Serializable; 021import java.lang.annotation.Annotation; 022import java.util.ArrayList; 023import java.util.HashMap; 024import java.util.Iterator; 025import java.util.List; 026import java.util.Locale; 027import java.util.Map; 028import java.util.Map.Entry; 029 030import org.springframework.beans.BeansException; 031import org.springframework.beans.factory.BeanFactory; 032import org.springframework.beans.factory.BeanNotOfRequiredTypeException; 033import org.springframework.beans.factory.FactoryBean; 034import org.springframework.beans.factory.NoSuchBeanDefinitionException; 035import org.springframework.beans.factory.ObjectProvider; 036import org.springframework.beans.factory.config.AutowireCapableBeanFactory; 037import org.springframework.context.ApplicationContext; 038import org.springframework.context.ApplicationEvent; 039import org.springframework.context.MessageSourceResolvable; 040import org.springframework.context.NoSuchMessageException; 041import org.springframework.core.ResolvableType; 042import org.springframework.core.env.Environment; 043import org.springframework.core.io.Resource; 044 045/** 046 * Mock application context object. This mock context allows easy creation of unit tests by allowing 047 * the user to put bean instances into the context. 048 * 049 * Only {@link #getBean(String)}, {@link #getBean(String, Class)}, and 050 * {@link #getBeansOfType(Class) 051 * } are implemented so far. Any other method throws 052 * {@link UnsupportedOperationException}. 053 * 054 * @author Igor Vaynberg (ivaynberg) 055 * 056 */ 057public class ApplicationContextMock implements ApplicationContext, Serializable 058{ 059 private static final long serialVersionUID = 1L; 060 061 private final Map<String, Object> beans = new HashMap<>(); 062 063 /** 064 * puts bean with the given name into the context 065 * 066 * @param name 067 * @param bean 068 */ 069 public void putBean(final String name, final Object bean) 070 { 071 if (beans.containsKey(name)) 072 { 073 throw new IllegalArgumentException("a bean with name [" + name + 074 "] has already been added to the context"); 075 } 076 beans.put(name, bean); 077 } 078 079 /** 080 * puts bean with into the context. bean object's class name will be used as the bean name. 081 * 082 * @param bean 083 */ 084 public void putBean(final Object bean) 085 { 086 putBean(bean.getClass().getName(), bean); 087 } 088 089 @Override 090 public Object getBean(final String name) throws BeansException 091 { 092 Object bean = beans.get(name); 093 if (bean == null) 094 { 095 throw new NoSuchBeanDefinitionException(name); 096 } 097 return bean; 098 } 099 100 @Override 101 public Object getBean(final String name, final Object... args) throws BeansException 102 { 103 return getBean(name); 104 } 105 106 /** 107 * @see org.springframework.beans.factory.BeanFactory#getBean(java.lang.String, java.lang.Class) 108 */ 109 @Override 110 @SuppressWarnings({ "unchecked" }) 111 public <T> T getBean(String name, Class<T> requiredType) throws BeansException 112 { 113 Object bean = getBean(name); 114 if (!(requiredType.isAssignableFrom(bean.getClass()))) 115 { 116 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); 117 } 118 return (T)bean; 119 } 120 121 /** 122 * @see org.springframework.beans.factory.ListableBeanFactory#getBeansOfType(java.lang.Class) 123 */ 124 @Override 125 @SuppressWarnings({ "unchecked" }) 126 public <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException 127 { 128 final Map<String, T> found = new HashMap<>(); 129 130 for (Entry<String, Object> entry : beans.entrySet()) 131 { 132 if (type.isAssignableFrom(entry.getValue().getClass())) 133 { 134 found.put(entry.getKey(), (T)entry.getValue()); 135 } 136 } 137 138 return found; 139 } 140 141 @Override 142 public <T> T getBean(Class<T> requiredType) throws BeansException 143 { 144 Iterator<T> beans = getBeansOfType(requiredType).values().iterator(); 145 146 if (beans.hasNext() == false) 147 { 148 throw new NoSuchBeanDefinitionException("bean of required type " + requiredType + 149 " not found"); 150 } 151 final T bean = beans.next(); 152 153 if (beans.hasNext() != false) 154 { 155 throw new NoSuchBeanDefinitionException("more than one bean of required type " + 156 requiredType + " found"); 157 } 158 return bean; 159 } 160 161 @Override 162 public <T> T getBean(Class<T> requiredType, Object... objects) throws BeansException 163 { 164 return getBean(requiredType); 165 } 166 167 @Override 168 public <T> ObjectProvider<T> getBeanProvider(Class<T> aClass) 169 { 170 return null; 171 } 172 173 @Override 174 public <T> ObjectProvider<T> getBeanProvider(ResolvableType resolvableType) 175 { 176 return null; 177 } 178 179 @Override 180 public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) 181 throws BeansException 182 { 183 final Map<String, Object> found = new HashMap<>(); 184 185 for (Entry<String, Object> entry : beans.entrySet()) 186 { 187 if (entry.getValue().getClass().isAnnotationPresent(annotationType)) 188 { 189 found.put(entry.getKey(), entry.getValue()); 190 } 191 } 192 return found; 193 } 194 195 @Override 196 public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType) 197 { 198 return findAnnotationOnClass(getBean(beanName).getClass(), annotationType); 199 } 200 201 @Override 202 public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException { 203 return findAnnotationOnClass(getBean(beanName).getClass(), annotationType); 204 } 205 206 private <A extends Annotation> A findAnnotationOnClass(Class<?> cls, Class<A> annotationType) 207 { 208 // lookup annotation type on class 209 A annotation = cls.getAnnotation(annotationType); 210 211 // lookup annotation type on superclass 212 if (annotation == null && cls.getSuperclass() != null) 213 { 214 annotation = findAnnotationOnClass(cls.getSuperclass(), annotationType); 215 } 216 217 // lookup annotation type on interfaces 218 if (annotation == null) 219 { 220 for (Class<?> intfClass : cls.getInterfaces()) 221 { 222 annotation = findAnnotationOnClass(intfClass, annotationType); 223 224 if (annotation != null) 225 { 226 break; 227 } 228 } 229 } 230 231 return annotation; 232 } 233 234 @Override 235 public ApplicationContext getParent() 236 { 237 throw new UnsupportedOperationException(); 238 } 239 240 @Override 241 public String getDisplayName() 242 { 243 throw new UnsupportedOperationException(); 244 } 245 246 @Override 247 public long getStartupDate() 248 { 249 throw new UnsupportedOperationException(); 250 } 251 252 @Override 253 public void publishEvent(final ApplicationEvent event) 254 { 255 throw new UnsupportedOperationException(); 256 } 257 258 @Override 259 public void publishEvent(Object o) 260 { 261 throw new UnsupportedOperationException(); 262 } 263 264 @Override 265 public boolean containsBeanDefinition(final String beanName) 266 { 267 return containsBean(beanName); 268 } 269 270 @Override 271 public int getBeanDefinitionCount() 272 { 273 return beans.size(); 274 } 275 276 @Override 277 public String[] getBeanDefinitionNames() 278 { 279 return beans.keySet().toArray(new String[0]); 280 } 281 282 @Override 283 public <T> ObjectProvider<T> getBeanProvider(final Class<T> aClass, final boolean b) { 284 return null; 285 } 286 287 @Override 288 public <T> ObjectProvider<T> getBeanProvider(final ResolvableType resolvableType, final boolean b) { 289 return null; 290 } 291 292 @Override 293 public String[] getBeanNamesForType(ResolvableType resolvableType) 294 { 295 return getBeanNamesForType(resolvableType, true, true); 296 } 297 298 @Override 299 public String[] getBeanNamesForType(ResolvableType resolvableType, boolean includeNonSingletons, boolean allowEagerInit) 300 { 301 List<String> names = new ArrayList<>(); 302 for (Entry<String, Object> entry : beans.entrySet()) 303 { 304 Object bean = entry.getValue(); 305 306 if (resolvableType.isAssignableFrom(bean.getClass())) 307 { 308 names.add(entry.getKey()); 309 } 310 } 311 return names.toArray(new String[0]); 312 } 313 314 @Override 315 @SuppressWarnings({ "unchecked" }) 316 public String[] getBeanNamesForType(final Class type) 317 { 318 ArrayList<String> names = new ArrayList<>(); 319 for (Entry<String, Object> entry : beans.entrySet()) 320 { 321 Object bean = entry.getValue(); 322 323 if (type.isAssignableFrom(bean.getClass())) 324 { 325 names.add(entry.getKey()); 326 } 327 } 328 return names.toArray(new String[names.size()]); 329 } 330 331 @Override 332 @SuppressWarnings({ "unchecked" }) 333 public String[] getBeanNamesForType(Class type, boolean includeNonSingletons, 334 boolean allowEagerInit) 335 { 336 throw new UnsupportedOperationException(); 337 } 338 339 @Override 340 public <T> Map<String, T> getBeansOfType(Class<T> type, boolean includeNonSingletons, 341 boolean allowEagerInit) throws BeansException 342 { 343 throw new UnsupportedOperationException(); 344 } 345 346 @Override 347 public String[] getBeanNamesForAnnotation(Class<? extends Annotation> aClass) 348 { 349 throw new UnsupportedOperationException(); 350 } 351 352 @Override 353 public boolean containsBean(final String name) 354 { 355 return beans.containsKey(name); 356 } 357 358 @Override 359 public boolean isSingleton(final String name) throws NoSuchBeanDefinitionException 360 { 361 return true; 362 } 363 364 @Override 365 public Class<?> getType(final String name) throws NoSuchBeanDefinitionException 366 { 367 return getType(name, true); 368 } 369 370 @Override 371 public Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException 372 { 373 Object bean = beans.get(name); 374 if (bean == null) 375 { 376 throw new NoSuchBeanDefinitionException("No bean with name '" + name + "'"); 377 } 378 379 if (bean instanceof FactoryBean) 380 { 381 return ((FactoryBean) bean).getObjectType(); 382 } 383 384 return bean.getClass(); 385 } 386 387 @Override 388 public String[] getAliases(final String name) throws NoSuchBeanDefinitionException 389 { 390 throw new UnsupportedOperationException(); 391 } 392 393 /** 394 * @see org.springframework.beans.factory.HierarchicalBeanFactory#getParentBeanFactory() 395 */ 396 @Override 397 public BeanFactory getParentBeanFactory() 398 { 399 return null; 400 } 401 402 @Override 403 public String getMessage(final String code, final Object[] args, final String defaultMessage, 404 final Locale locale) 405 { 406 throw new UnsupportedOperationException(); 407 } 408 409 @Override 410 public String getMessage(final String code, final Object[] args, final Locale locale) 411 throws NoSuchMessageException 412 { 413 throw new UnsupportedOperationException(); 414 } 415 416 @Override 417 public String getMessage(final MessageSourceResolvable resolvable, final Locale locale) 418 throws NoSuchMessageException 419 { 420 throw new UnsupportedOperationException(); 421 } 422 423 @Override 424 public Resource[] getResources(final String locationPattern) throws IOException 425 { 426 throw new UnsupportedOperationException(); 427 } 428 429 @Override 430 public Resource getResource(final String location) 431 { 432 throw new UnsupportedOperationException(); 433 } 434 435 @Override 436 public AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException 437 { 438 throw new UnsupportedOperationException(); 439 } 440 441 @Override 442 public boolean containsLocalBean(final String arg0) 443 { 444 throw new UnsupportedOperationException(); 445 } 446 447 @Override 448 public ClassLoader getClassLoader() 449 { 450 throw new UnsupportedOperationException(); 451 } 452 453 @Override 454 public String getId() 455 { 456 return null; 457 } 458 459 @Override 460 public String getApplicationName() 461 { 462 return ""; 463 } 464 465 @Override 466 public boolean isPrototype(final String name) throws NoSuchBeanDefinitionException 467 { 468 return !isSingleton(name); 469 } 470 471 @Override 472 public boolean isTypeMatch(String s, ResolvableType resolvableType) throws NoSuchBeanDefinitionException 473 { 474 return false; 475 } 476 477 @Override 478 @SuppressWarnings({ "unchecked" }) 479 public boolean isTypeMatch(final String name, final Class targetType) 480 throws NoSuchBeanDefinitionException 481 { 482 throw new UnsupportedOperationException(); 483 } 484 485 @Override 486 public Environment getEnvironment() 487 { 488 return null; 489 } 490}