package play.modules.spring; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.LinkedHashSet; import java.util.Set; import org.springframework.beans.factory.BeanDefinitionStoreException; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.ClassPathBeanDefinitionScanner; import org.springframework.context.annotation.ScannedGenericBeanDefinition; import org.springframework.core.io.AbstractResource; import org.springframework.core.io.ByteArrayResource; import org.springframework.core.io.InputStreamResource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.core.type.classreading.CachingMetadataReaderFactory; import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; import play.Logger; import play.Play; import play.classloading.ApplicationClasses.ApplicationClass; public class PlayClassPathBeanDefinitionScanner extends ClassPathBeanDefinitionScanner { private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory( this .resourcePatternResolver); /** * The constructor, which just passed on to the parent class. * * @param registry */ public PlayClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) { super(registry); } /** * The override, which searches through the play framework's classes, instead of using * files (as Spring is trained to do). */ @Override public Set<BeanDefinition> findCandidateComponents(String basePackage) { Logger.debug("Finding candidate components with base package: " + basePackage); Set<BeanDefinition> candidates = new LinkedHashSet<BeanDefinition>(); try { for (ApplicationClass appClass : Play.classes.all()) { if (appClass.name.startsWith(basePackage)) { Logger.debug("Scanning class: " + appClass.name); AbstractResource res = null; if (Play.usePrecompiled) { File f = Play.getFile("precompiled/java/" + (appClass.name.replace(".", "/")) + ".class"); res = new InputStreamResource(new FileInputStream(f)); } else { res = new ByteArrayResource(appClass.enhance()); } MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(res); if (isCandidateComponent(metadataReader)) { ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); sbd.setSource(res); if (isCandidateComponent(sbd)) { candidates.add(sbd); } } } else { Logger.trace("Skipped class: " + appClass.name + " -- wrong base package"); } } } catch (IOException ex) { throw new BeanDefinitionStoreException( "I/O failure during classpath scanning", ex); } return candidates; } }