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.cms.beans.config.ContentRepository;
37 import org.apache.commons.lang.StringUtils;
38 import org.apache.commons.lang.exception.ExceptionUtils;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 import java.lang.reflect.Modifier;
43 import java.util.HashMap;
44 import java.util.Map;
45 import java.util.Properties;
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 DefaultComponentProvider(Properties mappings) {
75
76
77 this.mappings = mappings;
78
79
80
81 }
82
83 public synchronized <T> T getSingleton(Class<T> type) {
84 T instance = (T) instances.get(type);
85 if (instance == null) {
86 log.debug("No instance for {} yet, creating new one.", type);
87 instance = newInstance(type);
88 instances.put(type, instance);
89 log.debug("New instance for {} created: {}", type, instance);
90 }
91
92 return instance;
93 }
94
95
96
97
98
99
100
101 public <T> T newInstance(Class<T> type) {
102 if (type == null) {
103 log.error("type can't be null", new Throwable());
104 return null;
105 }
106
107 try {
108 if (factories.containsKey(type)) {
109 final ComponentFactory<T> factory = (ComponentFactory<T>) factories.get(type);
110 return factory.newInstance();
111 }
112
113 final String className = getImplementationName(type);
114 if (isInRepositoryDefinition(className)) {
115 String repository = ContentRepository.CONFIG;
116 String path = className;
117 if (className.indexOf(':') >= 0) {
118 repository = StringUtils.substringBefore(className, ":");
119 path = StringUtils.substringAfter(className, ":");
120 }
121 final ObservedComponentFactory<T> factory = new ObservedComponentFactory<T>(repository, path, type);
122 setInstanceFactory(type, factory);
123
124 return newInstance(type);
125 } else {
126 final Class<?> clazz = Classes.getClassFactory().forName(className);
127 if (!isConcrete(clazz)) {
128 throw new MgnlInstantiationException("No concrete implementation defined for " + clazz);
129 }
130 final Object instance = Classes.getClassFactory().newInstance(clazz);
131
132 if (instance instanceof ComponentFactory) {
133 final ComponentFactory<T> factory = (ComponentFactory<T>) instance;
134 setInstanceFactory(type, factory);
135 return factory.newInstance();
136 }
137 return (T) instance;
138 }
139 } catch (Exception e) {
140 if (e instanceof MgnlInstantiationException) {
141 throw (MgnlInstantiationException) e;
142 }
143 throw new MgnlInstantiationException("Can't instantiate an implementation of this class [" + type.getName() + "]: " + ExceptionUtils.getMessage(e), e);
144 }
145 }
146
147 protected boolean isConcrete(Class<?> clazz) {
148 return !Modifier.isAbstract(clazz.getModifiers());
149 }
150
151
152 public <C> Class<? extends C> getImplementation(Class<C> type) throws ClassNotFoundException {
153 final String className = getImplementationName(type);
154 if (!isInRepositoryDefinition(className)) {
155 return (Class<? extends C>) Classes.getClassFactory().forName(className);
156 } else {
157 return type;
158 }
159 }
160
161 protected String getImplementationName(Class<?> type) {
162 final String name = type.getName();
163 return mappings.getProperty(name, name);
164 }
165
166 private boolean isInRepositoryDefinition(String className) {
167 return className.startsWith("/") || className.indexOf(':') >= 0;
168 }
169
170
171
172
173
174 public void setImplementation(Class<?> type, String impl) {
175 mappings.setProperty(type.getName(), impl);
176 }
177
178
179
180
181
182 public void setInstance(Class<?> type, Object instance) {
183 instances.put(type, instance);
184 }
185
186
187
188
189
190 public void setInstanceFactory(Class<?> type, ComponentFactory<?> factory) {
191 factories.put(type, factory);
192 }
193
194
195
196
197
198
199
200 public void clear() {
201 factories.clear();
202 instances.clear();
203 }
204
205 }