1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package de.smartics.properties.spi.core.registry;
17
18 import java.io.Serializable;
19 import java.util.HashMap;
20 import java.util.Map;
21 import java.util.Map.Entry;
22 import java.util.concurrent.locks.Lock;
23 import java.util.concurrent.locks.ReentrantReadWriteLock;
24
25 import javax.annotation.CheckForNull;
26 import javax.annotation.concurrent.ThreadSafe;
27
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 import de.smartics.properties.api.core.domain.ConfigException;
32 import de.smartics.properties.api.core.domain.PropertiesContext;
33 import de.smartics.properties.api.core.domain.PropertyDescriptor;
34 import de.smartics.properties.spi.core.context.DeclarationConfigParser;
35 import de.smartics.properties.spi.core.util.ClassLoaderUtils;
36 import de.smartics.util.lang.Arg;
37 import de.smartics.util.lang.classpath.ClassPathContext;
38
39
40
41
42
43
44 @ThreadSafe
45 public final class ConfigurationRegistry implements Serializable
46 {
47
48
49
50
51
52
53
54 private static final long serialVersionUID = 1L;
55
56
57
58
59 private static final Logger LOG = LoggerFactory
60 .getLogger(ConfigurationRegistry.class);
61
62
63
64
65
66
67
68
69 private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
70
71
72
73
74
75
76 private final Lock readLock = lock.readLock();
77
78
79
80
81
82
83 private final Lock writeLock = lock.writeLock();
84
85
86
87
88
89 private final Map<String, PropertiesContext> contexts =
90 new HashMap<String, PropertiesContext>();
91
92
93
94
95
96
97
98
99 public ConfigurationRegistry()
100 {
101 }
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121 @CheckForNull
122 public PropertiesContext get(final PropertyDescriptor descriptor)
123 throws NullPointerException
124 {
125 Arg.checkNotNull("descriptor", descriptor);
126
127 final Class<?> declaringType = descriptor.getDeclaringType();
128 return get(declaringType);
129 }
130
131
132
133
134
135
136
137
138
139 @CheckForNull
140 public PropertiesContext get(final Class<?> declaringType)
141 throws NullPointerException
142 {
143 Arg.checkNotNull("declaringType", declaringType);
144
145 final ClassLoader loader = declaringType.getClassLoader();
146 if (loader == null)
147 {
148 LOG.debug("Declaring type '{}' not registered as a property set.",
149 declaringType.getName());
150 return PropertiesContext.createEmptyContext();
151 }
152
153 try
154 {
155 final PropertiesContext context = load(declaringType);
156 return context;
157 }
158 catch (final ConfigException e)
159 {
160 LOG.debug("Cannot load properties context for declaring type '"
161 + declaringType.getName() + "'.", e);
162 return PropertiesContext.createEmptyContext();
163 }
164 }
165
166 private PropertiesContext load(final Class<?> declaringType)
167 throws ConfigException
168 {
169 final String archivePath = ClassLoaderUtils.calcArchivePath(declaringType);
170 final ClassPathContext cpContext =
171 new ClassPathContext(declaringType.getClassLoader(), archivePath);
172
173 readLock.lock();
174 try
175 {
176 PropertiesContext context = contexts.get(archivePath);
177 if (context == null)
178 {
179 readLock.unlock();
180 writeLock.lock();
181 try
182 {
183 context = contexts.get(archivePath);
184 if (context == null)
185 {
186 final DeclarationConfigParser parser =
187 new DeclarationConfigParser();
188 context = parser.parse(cpContext);
189
190 contexts.put(archivePath, context);
191 }
192 }
193 finally
194 {
195 readLock.lock();
196 writeLock.unlock();
197 }
198 }
199 return context;
200 }
201 finally
202 {
203 readLock.unlock();
204 }
205 }
206
207
208
209
210
211
212
213
214 @Override
215 public String toString()
216 {
217 final StringBuilder buffer = new StringBuilder();
218
219 for (final Entry<String, PropertiesContext> entry : contexts.entrySet())
220 {
221 buffer.append(entry.getKey()).append('=')
222 .append(entry.getValue().getHomePageUrl());
223 }
224
225 return buffer.toString();
226 }
227 }