1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.objectfactory;
35
36 import info.magnolia.init.MagnoliaConfigurationProperties;
37 import org.apache.commons.lang.exception.ExceptionUtils;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 import java.util.HashMap;
42 import java.util.Map;
43 import java.util.Properties;
44 import java.util.Set;
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 public class DefaultComponentProvider implements ComponentProvider {
60 private final static Logger log = LoggerFactory.getLogger(DefaultComponentProvider.class);
61
62
63
64
65 private final Map<Class<?>, Object> instances = new HashMap<Class<?>, Object>();
66
67
68
69
70 private final Map<Class<?>, ComponentFactory<?>> factories = new HashMap<Class<?>, ComponentFactory<?>>();
71
72 private final Properties mappings;
73
74 public DefaultComponentProvider(final MagnoliaConfigurationProperties mappings) {
75 this(new Properties() {{
76 final Set<String> keys = mappings.getKeys();
77 for (String key : keys) {
78 put(key, mappings.getProperty(key));
79 }
80 }});
81 }
82
83 public DefaultComponentProvider(Properties mappings) {
84
85
86 this.mappings = mappings;
87
88
89
90 }
91
92 @Override
93 @Deprecated
94 public synchronized <T> T getSingleton(Class<T> type) {
95 return getComponent(type);
96 }
97
98 @Override
99 public synchronized <T> T getComponent(Class<T> type) {
100 T instance = (T) instances.get(type);
101 if (instance == null) {
102 log.debug("No instance for {} yet, creating new one.", type);
103 instance = newInstance(type);
104 instances.put(type, instance);
105 log.debug("New instance for {} created: {}", type, instance);
106 }
107
108 return instance;
109 }
110
111 @Override
112 public <T> T newInstance(Class<T> type, Object... parameters) {
113 if (type == null) {
114 log.error("type can't be null", new Throwable());
115 return null;
116 }
117
118 try {
119 if (factories.containsKey(type)) {
120 final ComponentFactory<T> factory = (ComponentFactory<T>) factories.get(type);
121 return factory.newInstance();
122 }
123
124 final String className = getImplementationName(type);
125 if (isInRepositoryDefinition(className)) {
126 final ComponentConfigurationPath path = new ComponentConfigurationPath(className);
127 final ObservedComponentFactory<T> factory = new ObservedComponentFactory<T>(path.getRepository(), path.getPath(), type, this);
128 setInstanceFactory(type, factory);
129
130 return newInstance(type);
131 }
132 final Class<?> clazz = Classes.getClassFactory().forName(className);
133 if (!Classes.isConcrete(clazz)) {
134 throw new MgnlInstantiationException("No concrete implementation defined for " + clazz);
135 }
136 final Object instance = Classes.getClassFactory().newInstance(clazz, parameters);
137
138 if (instance instanceof ComponentFactory) {
139 final ComponentFactory<T> factory = (ComponentFactory<T>) instance;
140 setInstanceFactory(type, factory);
141 return factory.newInstance();
142 }
143 return (T) instance;
144 } catch (Exception e) {
145 if (e instanceof MgnlInstantiationException) {
146 throw (MgnlInstantiationException) e;
147 }
148 throw new MgnlInstantiationException("Can't instantiate an implementation of this class [" + type.getName() + "]: " + ExceptionUtils.getMessage(e), e);
149 }
150 }
151
152 @Override
153 public <T> T newInstanceWithParameterResolvers(Class<T> type, ParameterResolver... parameters) {
154 throw new UnsupportedOperationException();
155 }
156
157
158
159
160 protected boolean isConcrete(Class<?> clazz) {
161 return Classes.isConcrete(clazz);
162 }
163
164
165 @Override
166 public <C> Class<? extends C> getImplementation(Class<C> type) throws ClassNotFoundException {
167 final String className = getImplementationName(type);
168 if (!isInRepositoryDefinition(className)) {
169 return (Class<? extends C>) Classes.getClassFactory().forName(className);
170 }
171 return type;
172 }
173
174 protected String getImplementationName(Class<?> type) {
175 final String name = type.getName();
176 return mappings.getProperty(name, name);
177 }
178
179 @Override
180 public ComponentProvider getParent() {
181 return null;
182 }
183
184
185
186
187 static boolean isInRepositoryDefinition(String className) {
188 return ComponentConfigurationPath.isComponentConfigurationPath(className);
189 }
190
191
192
193
194
195 public void setImplementation(Class<?> type, String impl) {
196 mappings.setProperty(type.getName(), impl);
197 }
198
199
200
201
202
203 public void setInstance(Class<?> type, Object instance) {
204 instances.put(type, instance);
205 }
206
207
208
209
210
211 public void setInstanceFactory(Class<?> type, ComponentFactory<?> factory) {
212 factories.put(type, factory);
213 }
214
215
216
217
218
219
220
221 public void clear() {
222 factories.clear();
223 instances.clear();
224 }
225
226 }