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