1 16 17 package org.springframework.orm.jpa.support; 18 19 import java.beans.PropertyDescriptor ; 20 import java.lang.reflect.AccessibleObject ; 21 import java.lang.reflect.Field ; 22 import java.lang.reflect.InvocationTargetException ; 23 import java.lang.reflect.Method ; 24 import java.util.HashMap ; 25 import java.util.LinkedList ; 26 import java.util.List ; 27 import java.util.Map ; 28 import java.util.Properties ; 29 30 import javax.naming.NamingException ; 31 import javax.persistence.EntityManager; 32 import javax.persistence.EntityManagerFactory; 33 import javax.persistence.PersistenceContext; 34 import javax.persistence.PersistenceContextType; 35 import javax.persistence.PersistenceProperty; 36 import javax.persistence.PersistenceUnit; 37 38 import org.apache.commons.logging.Log; 39 import org.apache.commons.logging.LogFactory; 40 41 import org.springframework.beans.BeansException; 42 import org.springframework.beans.PropertyValues; 43 import org.springframework.beans.factory.BeanFactory; 44 import org.springframework.beans.factory.BeanFactoryAware; 45 import org.springframework.beans.factory.BeanFactoryUtils; 46 import org.springframework.beans.factory.ListableBeanFactory; 47 import org.springframework.beans.factory.NoSuchBeanDefinitionException; 48 import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor; 49 import org.springframework.jndi.JndiLocatorSupport; 50 import org.springframework.orm.jpa.EntityManagerFactoryInfo; 51 import org.springframework.orm.jpa.ExtendedEntityManagerCreator; 52 import org.springframework.orm.jpa.SharedEntityManagerCreator; 53 import org.springframework.util.ObjectUtils; 54 import org.springframework.util.ReflectionUtils; 55 import org.springframework.util.StringUtils; 56 57 148 public class PersistenceAnnotationBeanPostProcessor extends JndiLocatorSupport 149 implements InstantiationAwareBeanPostProcessor, BeanFactoryAware { 150 151 protected final Log logger = LogFactory.getLog(getClass()); 152 153 private Map <String , String > persistenceUnits; 154 155 private Map <String , String > persistenceContexts; 156 157 private Map <String , String > extendedPersistenceContexts; 158 159 private ListableBeanFactory beanFactory; 160 161 private Map <Class <?>, List <AnnotatedMember>> classMetadata = new HashMap <Class <?>, List <AnnotatedMember>>(); 162 163 164 public PersistenceAnnotationBeanPostProcessor() { 165 setResourceRef(true); 166 } 167 168 169 187 public void setPersistenceUnits(Map <String , String > persistenceUnits) { 188 this.persistenceUnits = persistenceUnits; 189 } 190 191 204 public void setPersistenceContexts(Map <String , String > persistenceContexts) { 205 this.persistenceContexts = persistenceContexts; 206 } 207 208 221 public void setExtendedPersistenceContexts(Map <String , String > extendedPersistenceContexts) { 222 this.extendedPersistenceContexts = extendedPersistenceContexts; 223 } 224 225 public void setBeanFactory(BeanFactory beanFactory) { 226 if (beanFactory instanceof ListableBeanFactory) { 227 this.beanFactory = (ListableBeanFactory) beanFactory; 228 } 229 } 230 231 232 public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException { 233 return null; 234 } 235 236 public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { 237 List <AnnotatedMember> metadata = findClassMetadata(bean.getClass()); 238 for (AnnotatedMember member : metadata) { 239 member.inject(bean); 240 } 241 return true; 242 } 243 244 public PropertyValues postProcessPropertyValues( 245 PropertyValues pvs, PropertyDescriptor [] pds, Object bean, String beanName) throws BeansException { 246 247 return pvs; 248 } 249 250 public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 251 return bean; 252 } 253 254 public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 255 return bean; 256 } 257 258 259 private List <AnnotatedMember> findClassMetadata(Class <? extends Object > clazz) { 260 synchronized (this.classMetadata) { 261 List <AnnotatedMember> metadata = this.classMetadata.get(clazz); 262 if (metadata == null) { 263 final List <AnnotatedMember> newMetadata = new LinkedList <AnnotatedMember>(); 264 ReflectionUtils.doWithFields(clazz, new ReflectionUtils.FieldCallback() { 265 public void doWith(Field field) { 266 addIfPresent(newMetadata, field); 267 } 268 }); 269 ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() { 270 public void doWith(Method method) { 271 addIfPresent(newMetadata, method); 272 } 273 }); 274 metadata = newMetadata; 275 this.classMetadata.put(clazz, metadata); 276 } 277 return metadata; 278 } 279 } 280 281 private void addIfPresent(List <AnnotatedMember> metadata, AccessibleObject ao) { 282 PersistenceContext pc = ao.getAnnotation(PersistenceContext.class); 283 if (pc != null) { 284 Properties properties = null; 285 PersistenceProperty[] pps = pc.properties(); 286 if (!ObjectUtils.isEmpty(pps)) { 287 properties = new Properties (); 288 for (int i = 0; i < pps.length; i++) { 289 PersistenceProperty pp = pps[i]; 290 properties.setProperty(pp.name(), pp.value()); 291 } 292 } 293 metadata.add(new AnnotatedMember(ao, pc.unitName(), pc.type(), properties)); 294 } 295 else { 296 PersistenceUnit pu = ao.getAnnotation(PersistenceUnit.class); 297 if (pu != null) { 298 metadata.add(new AnnotatedMember(ao, pu.unitName())); 299 } 300 } 301 } 302 303 304 312 protected EntityManagerFactory getPersistenceUnit(String unitName) { 313 if (this.persistenceUnits != null) { 314 String jndiName = this.persistenceUnits.get(unitName != null ? unitName : ""); 315 if (jndiName == null && !StringUtils.hasLength(unitName) && this.persistenceUnits.size() == 1) { 316 jndiName = this.persistenceUnits.values().iterator().next(); 317 } 318 if (jndiName != null) { 319 try { 320 return (EntityManagerFactory) lookup(jndiName, EntityManagerFactory.class); 321 } 322 catch (NamingException ex) { 323 throw new IllegalStateException ("Could not obtain EntityManagerFactory [" + jndiName + "] from JNDI", ex); 324 } 325 } 326 } 327 return null; 328 } 329 330 339 protected EntityManager getPersistenceContext(String unitName, boolean extended) { 340 Map <String , String > contexts = (extended ? this.extendedPersistenceContexts : this.persistenceContexts); 341 if (contexts != null) { 342 String jndiName = contexts.get(unitName != null ? unitName : ""); 343 if (jndiName == null && !StringUtils.hasLength(unitName) && contexts.size() == 1) { 344 jndiName = contexts.values().iterator().next(); 345 } 346 if (jndiName != null) { 347 try { 348 return (EntityManager) lookup(jndiName, EntityManager.class); 349 } 350 catch (NamingException ex) { 351 throw new IllegalStateException ("Could not obtain EntityManager [" + jndiName + "] from JNDI", ex); 352 } 353 } 354 } 355 return null; 356 } 357 358 366 protected EntityManagerFactory findEntityManagerFactory(String unitName) throws NoSuchBeanDefinitionException { 367 if (this.beanFactory == null) { 368 throw new IllegalStateException ("ListableBeanFactory required for EntityManagerFactory lookup"); 369 } 370 if (StringUtils.hasLength(unitName)) { 371 return findNamedEntityManagerFactory(unitName); 372 } 373 else { 374 return findDefaultEntityManagerFactory(); 375 } 376 } 377 378 385 protected EntityManagerFactory findNamedEntityManagerFactory(String unitName) throws NoSuchBeanDefinitionException { 386 String [] candidateNames = 387 BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, EntityManagerFactory.class); 388 for (String candidateName : candidateNames) { 389 EntityManagerFactory emf = (EntityManagerFactory) this.beanFactory.getBean(candidateName); 390 String nameToCompare = candidateName; 391 if (emf instanceof EntityManagerFactoryInfo) { 392 EntityManagerFactoryInfo emfi = (EntityManagerFactoryInfo) emf; 393 if (emfi.getPersistenceUnitName() != null) { 394 nameToCompare = emfi.getPersistenceUnitName(); 395 } 396 } 397 if (unitName.equals(nameToCompare)) { 398 return emf; 399 } 400 } 401 throw new NoSuchBeanDefinitionException(EntityManagerFactory.class, 402 "No EntityManagerFactory found for persistence unit name '" + unitName + "'"); 403 } 404 405 410 protected EntityManagerFactory findDefaultEntityManagerFactory() { 411 return (EntityManagerFactory) BeanFactoryUtils.beanOfTypeIncludingAncestors( 412 this.beanFactory, EntityManagerFactory.class); 413 } 414 415 416 420 private class AnnotatedMember { 421 422 private final AccessibleObject member; 423 424 private final String unitName; 425 426 private final PersistenceContextType type; 427 428 private final Properties properties; 429 430 public AnnotatedMember(AccessibleObject member, String unitName) { 431 this(member, unitName, null, null); 432 } 433 434 public AnnotatedMember(AccessibleObject member, String unitName, PersistenceContextType type, Properties properties) { 435 this.unitName = unitName; 436 this.type = type; 437 this.properties = properties; 438 this.member = member; 439 440 Class <?> memberType = getMemberType(); 442 if (!(EntityManagerFactory.class.isAssignableFrom(memberType) || 443 EntityManager.class.isAssignableFrom(memberType))) { 444 throw new IllegalArgumentException ("Cannot inject " + member + ": not a supported JPA type"); 445 } 446 } 447 448 public void inject(Object instance) { 449 Object value = resolve(); 450 try { 451 if (!this.member.isAccessible()) { 452 this.member.setAccessible(true); 453 } 454 if (this.member instanceof Field ) { 455 ((Field ) this.member).set(instance, value); 456 } 457 else if (this.member instanceof Method ) { 458 ((Method ) this.member).invoke(instance, value); 459 } 460 else { 461 throw new IllegalArgumentException ("Cannot inject unknown AccessibleObject type " + this.member); 462 } 463 } 464 catch (IllegalAccessException ex) { 465 throw new IllegalArgumentException ("Cannot inject member " + this.member, ex); 466 } 467 catch (InvocationTargetException ex) { 468 throw new IllegalArgumentException ("Attempt to inject setter method " + this.member + 470 " resulted in an exception", ex); 471 } 472 } 473 474 477 public Class <?> getMemberType() { 478 if (this.member instanceof Field ) { 479 return ((Field ) member).getType(); 480 } 481 else if (this.member instanceof Method ) { 482 Method setter = (Method ) this.member; 483 if (setter.getParameterTypes().length != 1) { 484 throw new IllegalArgumentException ( 485 "Supposed setter [" + this.member + "] must have 1 argument, not " + 486 setter.getParameterTypes().length); 487 } 488 return setter.getParameterTypes()[0]; 489 } 490 else { 491 throw new IllegalArgumentException ( 492 "Unknown AccessibleObject type [" + this.member.getClass() + 493 "]; can only inject setter methods and fields"); 494 } 495 } 496 497 500 private Object resolve() { 501 if (EntityManagerFactory.class.isAssignableFrom(getMemberType())) { 503 EntityManagerFactory emf = resolveEntityManagerFactory(); 504 if (!getMemberType().isInstance(emf)) { 505 throw new IllegalArgumentException ("Cannot inject [" + this.member + 506 "] with EntityManagerFactory [" + emf + "]: type mismatch"); 507 } 508 return emf; 509 } 510 else { 511 EntityManager em = (this.type == PersistenceContextType.EXTENDED ? 513 resolveExtendedEntityManager() : resolveEntityManager()); 514 if (!getMemberType().isInstance(em)) { 515 throw new IllegalArgumentException ("Cannot inject [" + this.member + 516 "] with EntityManager [" + em + "]: type mismatch"); 517 } 518 return em; 519 } 520 } 521 522 private EntityManagerFactory resolveEntityManagerFactory() { 523 EntityManagerFactory emf = getPersistenceUnit(this.unitName); 525 if (emf == null) { 526 emf = findEntityManagerFactory(this.unitName); 528 } 529 return emf; 530 } 531 532 private EntityManager resolveEntityManager() { 533 EntityManager em = getPersistenceContext(this.unitName, false); 535 if (em == null) { 536 EntityManagerFactory emf = getPersistenceUnit(this.unitName); 539 if (emf == null) { 540 emf = findEntityManagerFactory(this.unitName); 542 } 543 if (emf instanceof EntityManagerFactoryInfo && 545 !EntityManager.class.equals(((EntityManagerFactoryInfo) emf).getEntityManagerInterface())) { 546 em = SharedEntityManagerCreator.createSharedEntityManager(emf, this.properties); 549 } 550 else { 551 em = SharedEntityManagerCreator.createSharedEntityManager(emf, this.properties, getMemberType()); 553 } 554 } 555 return em; 556 } 557 558 private EntityManager resolveExtendedEntityManager() { 559 EntityManager em = getPersistenceContext(this.unitName, true); 561 if (em == null) { 562 EntityManagerFactory emf = getPersistenceUnit(this.unitName); 565 if (emf == null) { 566 emf = findEntityManagerFactory(this.unitName); 568 } 569 em = ExtendedEntityManagerCreator.createContainerManagedEntityManager(emf, this.properties); 571 } 572 return em; 573 } 574 } 575 576 } 577 | Popular Tags |