1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.apache.james.mailrepository;
23
24 import org.apache.avalon.cornerstone.services.store.Store;
25 import org.apache.avalon.framework.activity.Initializable;
26 import org.apache.avalon.framework.service.DefaultServiceManager;
27 import org.apache.avalon.framework.service.ServiceManager;
28 import org.apache.avalon.framework.service.ServiceException;
29 import org.apache.avalon.framework.service.Serviceable;
30 import org.apache.avalon.framework.configuration.Configurable;
31 import org.apache.avalon.framework.configuration.Configuration;
32 import org.apache.avalon.framework.configuration.ConfigurationException;
33 import org.apache.avalon.framework.configuration.DefaultConfiguration;
34 import org.apache.avalon.framework.container.ContainerUtil;
35 import org.apache.avalon.framework.logger.AbstractLogEnabled;
36 import org.apache.commons.collections.map.ReferenceMap;
37
38 import java.util.HashMap;
39 import java.util.Map;
40
41
42
43
44
45
46 public class AvalonMailStore
47 extends AbstractLogEnabled
48 implements Serviceable, Configurable, Initializable, Store {
49
50
51 private static final String REPOSITORY_NAME = "Repository";
52
53
54
55 private static long id;
56
57
58 private Map repositories;
59
60
61 private Map classes;
62
63
64 private Map defaultConfigs;
65
66
67
68
69 protected Configuration configuration;
70
71
72
73
74 protected ServiceManager m_manager;
75
76
77
78
79 public void service( final ServiceManager manager )
80 throws ServiceException
81 {
82 DefaultServiceManager def_manager = new DefaultServiceManager(manager);
83 def_manager.put(Store.ROLE, this);
84 m_manager = def_manager;
85 }
86
87
88
89
90
91 public void configure( final Configuration configuration )
92 throws ConfigurationException
93 {
94 this.configuration = configuration;
95 }
96
97
98
99
100 public void initialize()
101 throws Exception {
102
103 getLogger().info("JamesMailStore init...");
104 repositories = new ReferenceMap();
105 classes = new HashMap();
106 defaultConfigs = new HashMap();
107 Configuration[] registeredClasses
108 = configuration.getChild("repositories").getChildren("repository");
109 for ( int i = 0; i < registeredClasses.length; i++ )
110 {
111 registerRepository(registeredClasses[i]);
112 }
113
114 }
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129 public synchronized void registerRepository(Configuration repConf)
130 throws ConfigurationException {
131 String className = repConf.getAttribute("class");
132 boolean infoEnabled = getLogger().isInfoEnabled();
133 Configuration[] protocols
134 = repConf.getChild("protocols").getChildren("protocol");
135 Configuration[] types = repConf.getChild("types").getChildren("type");
136 for ( int i = 0; i < protocols.length; i++ )
137 {
138 String protocol = protocols[i].getValue();
139
140
141 Configuration defConf = repConf.getChild("config");
142
143 for ( int j = 0; j < types.length; j++ )
144 {
145 String type = types[j].getValue();
146 String key = protocol + type ;
147 if (infoEnabled) {
148 StringBuffer infoBuffer =
149 new StringBuffer(128)
150 .append("Registering Repository instance of class ")
151 .append(className)
152 .append(" to handle ")
153 .append(protocol)
154 .append(" protocol requests for repositories of type ")
155 .append(type);
156 getLogger().info(infoBuffer.toString());
157 }
158 if (classes.get(key) != null) {
159 throw new ConfigurationException("The combination of protocol and type comprise a unique key for repositories. This constraint has been violated. Please check your repository configuration.");
160 }
161 classes.put(key, className);
162 if (defConf != null) {
163 defaultConfigs.put(key, defConf);
164 }
165 }
166 }
167
168 }
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188 public synchronized Object select(Object hint) throws ServiceException {
189 Configuration repConf = null;
190 try {
191 repConf = (Configuration) hint;
192 } catch (ClassCastException cce) {
193 throw new ServiceException("",
194 "hint is of the wrong type. Must be a Configuration", cce);
195 }
196 String destination = null;
197 String protocol = null;
198 try {
199 destination = repConf.getAttribute("destinationURL");
200 int idx = destination.indexOf(':');
201 if ( idx == -1 )
202 throw new ServiceException("",
203 "destination is malformed. Must be a valid URL: "
204 + destination);
205 protocol = destination.substring(0,idx);
206 } catch (ConfigurationException ce) {
207 throw new ServiceException("",
208 "Malformed configuration has no destinationURL attribute", ce);
209 }
210
211 try
212 {
213 String type = repConf.getAttribute("type");
214 String repID = destination + type;
215 Object reply = repositories.get(repID);
216 StringBuffer logBuffer = null;
217 if (reply != null) {
218 if (getLogger().isDebugEnabled()) {
219 logBuffer =
220 new StringBuffer(128)
221 .append("obtained repository: ")
222 .append(repID)
223 .append(",")
224 .append(reply.getClass());
225 getLogger().debug(logBuffer.toString());
226 }
227 return reply;
228 } else {
229 String key = protocol + type;
230 String repClass = (String) classes.get( key );
231
232 if (getLogger().isDebugEnabled()) {
233 logBuffer =
234 new StringBuffer(128)
235 .append("obtained repository: ")
236 .append(repClass)
237 .append(" to handle: ")
238 .append(protocol)
239 .append(",")
240 .append(type);
241 getLogger().debug( logBuffer.toString() );
242 }
243
244
245
246
247
248 Configuration config;
249 Configuration defConf = (Configuration)defaultConfigs.get(key);
250 if ( defConf == null) {
251 config = repConf;
252 }
253 else {
254 config = new DefaultConfiguration(repConf.getName(),
255 repConf.getLocation());
256 copyConfig(defConf, (DefaultConfiguration)config);
257 copyConfig(repConf, (DefaultConfiguration)config);
258 }
259
260 try {
261 reply = Thread.currentThread().getContextClassLoader().loadClass(repClass).newInstance();
262 ContainerUtil.enableLogging(reply,getLogger());
263 ContainerUtil.service(reply,m_manager);
264
265 ContainerUtil.configure(reply,config);
266 ContainerUtil.initialize(reply);
267
268 repositories.put(repID, reply);
269 if (getLogger().isInfoEnabled()) {
270 logBuffer =
271 new StringBuffer(128)
272 .append("added repository: ")
273 .append(repID)
274 .append("->")
275 .append(repClass);
276 getLogger().info(logBuffer.toString());
277 }
278 return reply;
279 } catch (Exception e) {
280 if (getLogger().isWarnEnabled()) {
281 getLogger().warn( "Exception while creating repository:" +
282 e.getMessage(), e );
283 }
284 throw new
285 ServiceException("", "Cannot find or init repository",
286 e);
287 }
288 }
289 } catch( final ConfigurationException ce ) {
290 throw new ServiceException("", "Malformed configuration", ce );
291 }
292 }
293
294
295
296
297
298
299
300
301
302 public static final String getName() {
303 synchronized (AvalonMailStore.class) {
304 return REPOSITORY_NAME + id++;
305 }
306 }
307
308
309
310
311
312
313
314
315
316 public boolean isSelectable( Object hint ) {
317 Object comp = null;
318 try {
319 comp = select(hint);
320 } catch(ServiceException ex) {
321 if (getLogger().isErrorEnabled()) {
322 getLogger().error("Exception AvalonMailStore.hasComponent-" + ex.toString());
323 }
324 }
325 return (comp != null);
326 }
327
328
329
330
331
332
333
334
335 private void copyConfig(Configuration fromConfig, DefaultConfiguration toConfig)
336 {
337
338 String[] attrs = fromConfig.getAttributeNames();
339 for ( int i = 0; i < attrs.length; i++ ) {
340 String attrName = attrs[i];
341 String attrValue = fromConfig.getAttribute(attrName, null);
342 toConfig.setAttribute(attrName, attrValue);
343 }
344
345
346 Configuration[] children = fromConfig.getChildren();
347 for ( int i = 0; i < children.length; i++ ) {
348 Configuration child = children[i];
349 String childName = child.getName();
350 Configuration existingChild = toConfig.getChild(childName, false);
351 if ( existingChild == null ) {
352 toConfig.addChild(child);
353 }
354 else {
355 copyConfig(child, (DefaultConfiguration)existingChild);
356 }
357 }
358
359
360 String val = fromConfig.getValue(null);
361 if ( val != null ) {
362 toConfig.setValue(val);
363 }
364 }
365
366
367
368
369
370
371
372 public void release(Object component) {}
373 }