1 package com.atlassian.plugin.spring.scanner.runtime.impl;
2
3 import com.atlassian.plugin.spring.scanner.util.CommonConstants;
4 import org.osgi.framework.Bundle;
5 import org.osgi.framework.BundleContext;
6 import org.slf4j.Logger;
7 import org.slf4j.LoggerFactory;
8 import org.springframework.beans.factory.config.BeanDefinition;
9 import org.springframework.beans.factory.config.BeanDefinitionHolder;
10 import org.springframework.beans.factory.support.AbstractBeanDefinition;
11 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
12 import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
13 import org.springframework.beans.factory.support.BeanDefinitionRegistry;
14 import org.springframework.util.ClassUtils;
15
16 import java.beans.Introspector;
17 import java.util.HashMap;
18 import java.util.HashSet;
19 import java.util.LinkedHashSet;
20 import java.util.Map;
21 import java.util.Set;
22 import java.util.TreeSet;
23
24 import static com.atlassian.plugin.spring.scanner.runtime.impl.util.AnnotationIndexReader.getIndexFilesForProfiles;
25 import static com.atlassian.plugin.spring.scanner.runtime.impl.util.AnnotationIndexReader.readAllIndexFilesForProduct;
26 import static com.atlassian.plugin.spring.scanner.runtime.impl.util.AnnotationIndexReader.splitProfiles;
27 import static com.atlassian.plugin.spring.scanner.runtime.impl.util.BeanDefinitionChecker.needToRegister;
28
29
30
31
32
33
34 public class ClassIndexBeanDefinitionScanner {
35 private static final Logger log = LoggerFactory.getLogger(ClassIndexBeanDefinitionScanner.class);
36
37 private final BeanDefinitionRegistry registry;
38 private final String profileName;
39
40
41
42
43 private final Integer autowireDefault;
44 private final BundleContext bundleContext;
45
46 public ClassIndexBeanDefinitionScanner(
47 final BeanDefinitionRegistry registry,
48 final String profileName,
49 final Integer autowireDefault,
50 final BundleContext bundleContext) {
51 this.registry = registry;
52 this.profileName = profileName;
53 this.autowireDefault = autowireDefault;
54 this.bundleContext = bundleContext;
55 }
56
57
58
59
60
61
62 protected Set<BeanDefinitionHolder> doScan() {
63
64 final Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
65 final Map<String, BeanDefinition> namesAndDefinitions = findCandidateComponents();
66
67 for (final Map.Entry<String, BeanDefinition> nameAndDefinition : namesAndDefinitions.entrySet()) {
68
69 if (needToRegister(nameAndDefinition.getKey(), nameAndDefinition.getValue(), registry)) {
70 final BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(
71 nameAndDefinition.getValue(), nameAndDefinition.getKey());
72 beanDefinitions.add(definitionHolder);
73 registerBeanDefinition(definitionHolder, registry);
74 }
75 }
76 return beanDefinitions;
77 }
78
79
80
81
82
83
84 public Map<String, BeanDefinition> findCandidateComponents() {
85 final Map<String, BeanDefinition> candidates = new HashMap<String, BeanDefinition>();
86
87 final Bundle bundle = bundleContext.getBundle();
88
89 final Set<String> beanTypeAndNames = new TreeSet<String>();
90
91 final String[] profileNames = splitProfiles(profileName);
92 for (final String fileToRead : getIndexFilesForProfiles(profileNames, CommonConstants.COMPONENT_KEY)) {
93 beanTypeAndNames.addAll(readAllIndexFilesForProduct(fileToRead, bundle, bundleContext));
94 }
95 final Set<String> primaryComponentTypeAndNames = findPrimaryComponentTypeAndNames(profileNames, bundle);
96
97 for (final String beanTypeAndName : beanTypeAndNames) {
98 final String[] typeAndName = beanTypeAndName.split("#");
99
100 final String beanClassName = typeAndName[0];
101 String beanName = "";
102
103 if (typeAndName.length > 1) {
104 beanName = typeAndName[1];
105 }
106
107 if (beanName.isEmpty()) {
108 beanName = Introspector.decapitalize(ClassUtils.getShortName(beanClassName));
109 }
110
111 if (log.isDebugEnabled()) {
112 log.debug(String.format("Found candidate bean '%s' from class '%s'", beanName, beanClassName));
113 }
114
115 final BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(beanClassName);
116 if (null != autowireDefault) {
117 beanDefinitionBuilder.setAutowireMode(autowireDefault);
118 }
119
120 final BeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
121 if (primaryComponentTypeAndNames.contains(beanTypeAndName)) {
122 beanDefinition.setPrimary(true);
123 }
124 candidates.put(beanName, beanDefinition);
125 }
126
127 return candidates;
128 }
129
130
131
132
133
134
135
136
137 private Set<String> findPrimaryComponentTypeAndNames(String[] profileNames, Bundle bundle) {
138 final Set<String> beanTypeAndNames = new HashSet<>();
139 for (final String fileToRead : getIndexFilesForProfiles(profileNames, CommonConstants.COMPONENT_PRIMARY_KEY)) {
140 beanTypeAndNames.addAll(readAllIndexFilesForProduct(fileToRead, bundle, bundleContext));
141 }
142 return beanTypeAndNames;
143 }
144
145
146
147
148 protected void registerBeanDefinition(final BeanDefinitionHolder definitionHolder, final BeanDefinitionRegistry registry) {
149 BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
150 }
151 }