1 | |
package org.apache.fulcrum.intake; |
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
|
18 | |
|
19 | |
|
20 | |
|
21 | |
|
22 | |
import java.beans.IntrospectionException; |
23 | |
import java.beans.PropertyDescriptor; |
24 | |
import java.io.File; |
25 | |
import java.io.FileInputStream; |
26 | |
import java.io.FileOutputStream; |
27 | |
import java.io.IOException; |
28 | |
import java.io.ObjectInputStream; |
29 | |
import java.io.ObjectOutputStream; |
30 | |
import java.lang.reflect.Method; |
31 | |
import java.net.URL; |
32 | |
import java.util.ArrayList; |
33 | |
import java.util.HashMap; |
34 | |
import java.util.HashSet; |
35 | |
import java.util.List; |
36 | |
import java.util.ListIterator; |
37 | |
import java.util.Map; |
38 | |
import java.util.Map.Entry; |
39 | |
import java.util.Set; |
40 | |
|
41 | |
import javax.xml.XMLConstants; |
42 | |
import javax.xml.bind.JAXBContext; |
43 | |
import javax.xml.bind.Unmarshaller; |
44 | |
import javax.xml.bind.Unmarshaller.Listener; |
45 | |
import javax.xml.bind.helpers.DefaultValidationEventHandler; |
46 | |
import javax.xml.validation.SchemaFactory; |
47 | |
|
48 | |
import org.apache.avalon.framework.activity.Initializable; |
49 | |
import org.apache.avalon.framework.configuration.Configurable; |
50 | |
import org.apache.avalon.framework.configuration.Configuration; |
51 | |
import org.apache.avalon.framework.configuration.ConfigurationException; |
52 | |
import org.apache.avalon.framework.context.Context; |
53 | |
import org.apache.avalon.framework.context.ContextException; |
54 | |
import org.apache.avalon.framework.context.Contextualizable; |
55 | |
import org.apache.avalon.framework.logger.AbstractLogEnabled; |
56 | |
import org.apache.avalon.framework.logger.LogEnabled; |
57 | |
import org.apache.avalon.framework.service.ServiceException; |
58 | |
import org.apache.avalon.framework.service.ServiceManager; |
59 | |
import org.apache.avalon.framework.service.Serviceable; |
60 | |
import org.apache.commons.pool2.KeyedObjectPool; |
61 | |
import org.apache.commons.pool2.KeyedPooledObjectFactory; |
62 | |
import org.apache.commons.pool2.impl.GenericKeyedObjectPool; |
63 | |
import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig; |
64 | |
import org.apache.fulcrum.intake.model.AppData; |
65 | |
import org.apache.fulcrum.intake.model.Field; |
66 | |
import org.apache.fulcrum.intake.model.Group; |
67 | |
|
68 | |
|
69 | |
|
70 | |
|
71 | |
|
72 | |
|
73 | |
|
74 | |
|
75 | |
|
76 | |
|
77 | |
|
78 | |
|
79 | |
|
80 | 54 | public class IntakeServiceImpl extends AbstractLogEnabled implements |
81 | |
IntakeService, Configurable, Initializable, Contextualizable, |
82 | |
Serviceable |
83 | |
{ |
84 | |
|
85 | |
private Map<String, AppData> groupNames; |
86 | |
|
87 | |
|
88 | |
private Map<String, String> groupNameMap; |
89 | |
|
90 | |
|
91 | |
private Map<String, String> groupKeyMap; |
92 | |
|
93 | |
|
94 | |
private Map<String, Map<String, Method>> getterMap; |
95 | |
|
96 | |
|
97 | |
private Map<String, Map<String, Method>> setterMap; |
98 | |
|
99 | |
|
100 | |
private Map<AppData, KeyedObjectPool<String, Group>> keyedPools; |
101 | |
|
102 | |
|
103 | |
private String applicationRoot; |
104 | |
|
105 | |
|
106 | 20 | private List<String> xmlPathes = null; |
107 | |
|
108 | |
|
109 | 20 | private String serialDataPath = null; |
110 | |
|
111 | |
|
112 | |
|
113 | |
|
114 | |
|
115 | 2 | private class AvalonLogEnabledListener extends Listener |
116 | |
{ |
117 | |
|
118 | |
|
119 | |
|
120 | |
@Override |
121 | |
public void beforeUnmarshal(Object target, Object parent) |
122 | |
{ |
123 | 80 | super.beforeUnmarshal(target, parent); |
124 | |
|
125 | 80 | if (target instanceof LogEnabled) |
126 | |
{ |
127 | 34 | ((LogEnabled)target).enableLogging(getLogger()); |
128 | |
} |
129 | 80 | } |
130 | |
|
131 | |
} |
132 | |
|
133 | |
|
134 | |
|
135 | |
|
136 | |
|
137 | |
|
138 | |
|
139 | |
|
140 | |
|
141 | |
|
142 | |
|
143 | |
|
144 | |
|
145 | |
|
146 | |
|
147 | |
private boolean registerGroup(String groupName, Group group, |
148 | |
AppData appData, boolean checkKey) |
149 | |
{ |
150 | 120 | if (groupNames.containsKey(groupName)) |
151 | |
{ |
152 | |
|
153 | 0 | return false; |
154 | |
} |
155 | |
|
156 | 120 | boolean keyExists = groupNameMap.containsKey(group.getGID()); |
157 | |
|
158 | 120 | if (checkKey && keyExists) |
159 | |
{ |
160 | |
|
161 | 0 | return false; |
162 | |
} |
163 | |
|
164 | 120 | groupNames.put(groupName, appData); |
165 | 120 | groupKeyMap.put(groupName, group.getGID()); |
166 | |
|
167 | 120 | if (!keyExists) |
168 | |
{ |
169 | |
|
170 | 120 | groupNameMap.put(group.getGID(), groupName); |
171 | |
} |
172 | |
|
173 | 120 | List<Field<?>> fields = group.getFields(); |
174 | 120 | for (Field<?> field : fields) |
175 | |
{ |
176 | 560 | String className = field.getMapToObject(); |
177 | 560 | if (!getterMap.containsKey(className)) |
178 | |
{ |
179 | 80 | getterMap.put(className, new HashMap<String, Method>()); |
180 | 80 | setterMap.put(className, new HashMap<String, Method>()); |
181 | |
} |
182 | 560 | } |
183 | 120 | return true; |
184 | |
} |
185 | |
|
186 | |
|
187 | |
|
188 | |
|
189 | |
|
190 | |
|
191 | |
|
192 | |
|
193 | |
|
194 | |
|
195 | |
|
196 | |
private Map<AppData, File> loadSerialized(String serialDataPath, long timeStamp) |
197 | |
{ |
198 | 20 | getLogger().debug( |
199 | |
"Entered loadSerialized(" + serialDataPath + ", " + timeStamp |
200 | |
+ ")"); |
201 | |
|
202 | 20 | long timer = System.currentTimeMillis(); |
203 | |
|
204 | 20 | if (serialDataPath == null) |
205 | |
{ |
206 | 0 | return null; |
207 | |
} |
208 | |
|
209 | 20 | File serialDataFile = new File(serialDataPath); |
210 | |
|
211 | 20 | if (!serialDataFile.exists()) |
212 | |
{ |
213 | 1 | getLogger().info("No serialized file found, parsing XML"); |
214 | 1 | return null; |
215 | |
} |
216 | |
|
217 | 19 | if (serialDataFile.lastModified() <= timeStamp) |
218 | |
{ |
219 | 0 | getLogger().info("serialized file too old, parsing XML"); |
220 | 0 | return null; |
221 | |
} |
222 | |
|
223 | 19 | ObjectInputStream in = null; |
224 | 19 | Map<AppData, File> serialData = null; |
225 | |
|
226 | |
try |
227 | |
{ |
228 | 19 | FileInputStream fin = new FileInputStream(serialDataFile); |
229 | 19 | in = new ObjectInputStream(fin); |
230 | 19 | Object o = in.readObject(); |
231 | |
|
232 | 19 | if (o instanceof Map) |
233 | |
{ |
234 | |
@SuppressWarnings("unchecked") |
235 | 19 | Map<AppData, File> map = (Map<AppData, File>) o; |
236 | 19 | serialData = map; |
237 | 19 | } |
238 | |
else |
239 | |
{ |
240 | |
|
241 | 0 | getLogger().info("serialized object is not an intake map, ignoring"); |
242 | 0 | in.close(); |
243 | 0 | in = null; |
244 | |
|
245 | |
|
246 | 0 | boolean result = serialDataFile.delete(); |
247 | 0 | if ( result == false ) |
248 | |
{ |
249 | 0 | getLogger().error("Unknown serialized file could not be removed"); |
250 | |
} |
251 | |
} |
252 | |
} |
253 | 0 | catch (IOException e) |
254 | |
{ |
255 | 0 | getLogger().error("Serialized File could not be read.", e); |
256 | |
|
257 | |
|
258 | |
|
259 | 0 | serialData = null; |
260 | |
} |
261 | 0 | catch (ClassNotFoundException e) |
262 | |
{ |
263 | 0 | getLogger().error("Objects could not be read from serialized file.", e); |
264 | |
|
265 | |
|
266 | |
|
267 | 0 | serialData = null; |
268 | |
} |
269 | |
finally |
270 | |
{ |
271 | |
|
272 | |
|
273 | 0 | try |
274 | |
{ |
275 | 19 | if (in != null) |
276 | |
{ |
277 | 19 | in.close(); |
278 | |
} |
279 | |
} |
280 | 0 | catch (IOException e) |
281 | |
{ |
282 | 0 | getLogger().error("Exception while closing file", e); |
283 | 19 | } |
284 | 0 | } |
285 | |
|
286 | |
|
287 | 19 | if (serialData != null) |
288 | |
{ |
289 | 19 | for (AppData appData : serialData.keySet()) |
290 | |
{ |
291 | 38 | for (Group group : appData.getGroups()) |
292 | |
{ |
293 | 114 | if (group instanceof LogEnabled) |
294 | |
{ |
295 | 114 | ((LogEnabled)group).enableLogging(getLogger()); |
296 | |
} |
297 | |
|
298 | 114 | for (Field<?> field : group.getFields()) |
299 | |
{ |
300 | 532 | if (field instanceof LogEnabled) |
301 | |
{ |
302 | 532 | ((LogEnabled)field).enableLogging(getLogger()); |
303 | |
} |
304 | 532 | } |
305 | 114 | } |
306 | 38 | } |
307 | |
} |
308 | 19 | getLogger().info("Loaded serialized map object, ignoring XML"); |
309 | 19 | getLogger().debug("Loading took " + (System.currentTimeMillis() - timer)); |
310 | 19 | return serialData; |
311 | |
} |
312 | |
|
313 | |
|
314 | |
|
315 | |
|
316 | |
|
317 | |
|
318 | |
|
319 | |
|
320 | |
|
321 | |
|
322 | |
|
323 | |
private void saveSerialized(String serialDataPath, Map<AppData, File> appDataElements) |
324 | |
{ |
325 | |
|
326 | 1 | getLogger().debug( |
327 | |
"Entered saveSerialized(" + serialDataPath |
328 | |
+ ", appDataElements)"); |
329 | |
|
330 | 1 | long timer = System.currentTimeMillis(); |
331 | |
|
332 | 1 | if (serialDataPath == null) |
333 | |
{ |
334 | 0 | return; |
335 | |
} |
336 | |
|
337 | 1 | File serialData = new File(serialDataPath); |
338 | |
|
339 | |
try |
340 | |
{ |
341 | 1 | boolean result = serialData.createNewFile(); |
342 | 1 | if ( result == false ) |
343 | |
{ |
344 | 0 | getLogger().error("Could not create new serialized file"); |
345 | |
} |
346 | |
|
347 | |
|
348 | 1 | result = serialData.delete(); |
349 | 1 | if ( result == false ) |
350 | |
{ |
351 | 0 | getLogger().error("Serialized file could not be removed"); |
352 | |
} |
353 | |
|
354 | |
} |
355 | 0 | catch (IOException e) |
356 | |
{ |
357 | 0 | getLogger().info( |
358 | |
"Could not create serialized file " + serialDataPath |
359 | |
+ ", not serializing the XML data", e); |
360 | 0 | return; |
361 | 1 | } |
362 | |
|
363 | 1 | ObjectOutputStream out = null; |
364 | 1 | ObjectInputStream in = null; |
365 | |
|
366 | |
try |
367 | |
{ |
368 | |
|
369 | 1 | FileOutputStream fout = new FileOutputStream(serialDataPath); |
370 | 1 | out = new ObjectOutputStream(fout); |
371 | 1 | out.writeObject(appDataElements); |
372 | 1 | out.flush(); |
373 | |
|
374 | |
|
375 | |
|
376 | 1 | FileInputStream fin = new FileInputStream(serialDataPath); |
377 | 1 | in = new ObjectInputStream(fin); |
378 | 1 | in.readObject(); |
379 | |
|
380 | 1 | getLogger().debug("Serializing successful"); |
381 | |
} |
382 | 0 | catch (IOException e) |
383 | |
{ |
384 | 0 | getLogger().info( |
385 | |
"Could not write serialized file to " + serialDataPath |
386 | |
+ ", not serializing the XML data", e); |
387 | |
} |
388 | 0 | catch (ClassNotFoundException e) |
389 | |
{ |
390 | 0 | getLogger().info( |
391 | |
"Could not re-read serialized file from " + serialDataPath, e); |
392 | |
} |
393 | |
finally |
394 | |
{ |
395 | 0 | try |
396 | |
{ |
397 | 1 | if (out != null) |
398 | |
{ |
399 | 1 | out.close(); |
400 | |
} |
401 | |
} |
402 | 0 | catch (IOException e) |
403 | |
{ |
404 | 0 | getLogger().error("Exception while closing file", e); |
405 | 1 | } |
406 | |
try |
407 | |
{ |
408 | 1 | if (in != null) |
409 | |
{ |
410 | 1 | in.close(); |
411 | |
} |
412 | |
} |
413 | 0 | catch (IOException e) |
414 | |
{ |
415 | 0 | getLogger().error("Exception while closing file", e); |
416 | 1 | } |
417 | 0 | } |
418 | |
|
419 | 1 | getLogger().debug("Saving took " + (System.currentTimeMillis() - timer)); |
420 | 1 | } |
421 | |
|
422 | |
|
423 | |
|
424 | |
|
425 | |
|
426 | |
|
427 | |
|
428 | |
|
429 | |
|
430 | |
|
431 | |
|
432 | |
@Override |
433 | |
public Group getGroup(String groupName) throws IntakeException |
434 | |
{ |
435 | 25 | Group group = null; |
436 | |
|
437 | 25 | AppData appData = groupNames.get(groupName); |
438 | |
|
439 | 25 | if (groupName == null) |
440 | |
{ |
441 | 0 | throw new IntakeException( |
442 | |
"Intake IntakeServiceImpl.getGroup(groupName) is null"); |
443 | |
} |
444 | |
|
445 | 25 | if (appData == null) |
446 | |
{ |
447 | 0 | throw new IntakeException( |
448 | |
"Intake IntakeServiceImpl.getGroup(groupName): No XML definition for Group " |
449 | |
+ groupName + " found"); |
450 | |
} |
451 | |
try |
452 | |
{ |
453 | 25 | group = keyedPools.get(appData).borrowObject(groupName); |
454 | |
} |
455 | 0 | catch (Exception e) |
456 | |
{ |
457 | 0 | throw new IntakeException("Could not get group " + groupName, e); |
458 | 25 | } |
459 | 25 | return group; |
460 | |
} |
461 | |
|
462 | |
|
463 | |
|
464 | |
|
465 | |
|
466 | |
|
467 | |
|
468 | |
|
469 | |
|
470 | |
|
471 | |
@Override |
472 | |
public void releaseGroup(Group instance) throws IntakeException |
473 | |
{ |
474 | 0 | if (instance != null) |
475 | |
{ |
476 | 0 | String groupName = instance.getIntakeGroupName(); |
477 | 0 | AppData appData = groupNames.get(groupName); |
478 | |
|
479 | 0 | if (appData == null) |
480 | |
{ |
481 | 0 | throw new IntakeException( |
482 | |
"Intake IntakeServiceImpl.releaseGroup(groupName): " |
483 | |
+ "No XML definition for Group " + groupName |
484 | |
+ " found"); |
485 | |
} |
486 | |
|
487 | |
try |
488 | |
{ |
489 | 0 | keyedPools.get(appData).returnObject(groupName, instance); |
490 | |
} |
491 | 0 | catch (Exception e) |
492 | |
{ |
493 | 0 | throw new IntakeException("Could not get group " + groupName, e); |
494 | 0 | } |
495 | |
} |
496 | 0 | } |
497 | |
|
498 | |
|
499 | |
|
500 | |
|
501 | |
|
502 | |
|
503 | |
|
504 | |
|
505 | |
|
506 | |
|
507 | |
@Override |
508 | |
public int getSize(String groupName) throws IntakeException |
509 | |
{ |
510 | 0 | AppData appData = groupNames.get(groupName); |
511 | 0 | if (appData == null) |
512 | |
{ |
513 | 0 | throw new IntakeException( |
514 | |
"Intake IntakeServiceImpl.Size(groupName): No XML definition for Group " |
515 | |
+ groupName + " found"); |
516 | |
} |
517 | |
|
518 | 0 | KeyedObjectPool<String, Group> kop = keyedPools.get(appData); |
519 | |
|
520 | 0 | return kop.getNumActive(groupName) + kop.getNumIdle(groupName); |
521 | |
} |
522 | |
|
523 | |
|
524 | |
|
525 | |
|
526 | |
|
527 | |
|
528 | |
@Override |
529 | |
public String[] getGroupNames() |
530 | |
{ |
531 | 0 | return groupNames.keySet().toArray(new String[0]); |
532 | |
} |
533 | |
|
534 | |
|
535 | |
|
536 | |
|
537 | |
|
538 | |
|
539 | |
|
540 | |
|
541 | |
@Override |
542 | |
public String getGroupKey(String groupName) |
543 | |
{ |
544 | 0 | return groupKeyMap.get(groupName); |
545 | |
} |
546 | |
|
547 | |
|
548 | |
|
549 | |
|
550 | |
|
551 | |
|
552 | |
|
553 | |
|
554 | |
@Override |
555 | |
public String getGroupName(String groupKey) |
556 | |
{ |
557 | 0 | return groupNameMap.get(groupKey); |
558 | |
} |
559 | |
|
560 | |
|
561 | |
|
562 | |
|
563 | |
|
564 | |
|
565 | |
|
566 | |
|
567 | |
|
568 | |
|
569 | |
|
570 | |
|
571 | |
@Override |
572 | |
public Method getFieldSetter(String className, String propName) |
573 | |
throws ClassNotFoundException, IntrospectionException |
574 | |
{ |
575 | 60 | Map<String, Method> settersForClassName = setterMap.get(className); |
576 | |
|
577 | 60 | if (settersForClassName == null) |
578 | |
{ |
579 | 0 | throw new IntrospectionException("No setter Map for " + className |
580 | |
+ " available!"); |
581 | |
} |
582 | |
|
583 | 60 | Method setter = settersForClassName.get(propName); |
584 | |
|
585 | 60 | if (setter == null) |
586 | |
{ |
587 | 60 | PropertyDescriptor pd = new PropertyDescriptor(propName, Class |
588 | 60 | .forName(className)); |
589 | 60 | synchronized (setterMap) |
590 | |
{ |
591 | 60 | setter = pd.getWriteMethod(); |
592 | 60 | settersForClassName.put(propName, setter); |
593 | 60 | if (setter == null) |
594 | |
{ |
595 | 0 | getLogger().error( |
596 | |
"Intake: setter for '" + propName + "' in class '" |
597 | |
+ className + "' could not be found."); |
598 | |
} |
599 | 60 | } |
600 | |
|
601 | |
|
602 | 60 | synchronized (getterMap) |
603 | |
{ |
604 | 60 | Map<String, Method> gettersForClassName = getterMap.get(className); |
605 | |
|
606 | 60 | if (gettersForClassName != null) |
607 | |
{ |
608 | 60 | Method getter = pd.getReadMethod(); |
609 | 60 | if (getter != null) |
610 | |
{ |
611 | 60 | gettersForClassName.put(propName, getter); |
612 | |
} |
613 | |
} |
614 | 60 | } |
615 | |
} |
616 | 60 | return setter; |
617 | |
} |
618 | |
|
619 | |
|
620 | |
|
621 | |
|
622 | |
|
623 | |
|
624 | |
|
625 | |
|
626 | |
|
627 | |
|
628 | |
|
629 | |
|
630 | |
@Override |
631 | |
public Method getFieldGetter(String className, String propName) |
632 | |
throws ClassNotFoundException, IntrospectionException |
633 | |
{ |
634 | 60 | Map<String, Method> gettersForClassName = getterMap.get(className); |
635 | |
|
636 | 60 | if (gettersForClassName == null) |
637 | |
{ |
638 | 0 | throw new IntrospectionException("No getter Map for " + className |
639 | |
+ " available!"); |
640 | |
} |
641 | |
|
642 | 60 | Method getter = gettersForClassName.get(propName); |
643 | |
|
644 | 60 | if (getter == null) |
645 | |
{ |
646 | 60 | PropertyDescriptor pd = null; |
647 | 60 | synchronized (getterMap) |
648 | |
{ |
649 | 60 | pd = new PropertyDescriptor(propName, Class.forName(className)); |
650 | 60 | getter = pd.getReadMethod(); |
651 | 60 | gettersForClassName.put(propName, getter); |
652 | 60 | if (getter == null) |
653 | |
{ |
654 | 0 | getLogger().error( |
655 | |
"Intake: getter for '" + propName + "' in class '" |
656 | |
+ className + "' could not be found."); |
657 | |
} |
658 | 60 | } |
659 | |
|
660 | |
|
661 | 60 | synchronized (setterMap) |
662 | |
{ |
663 | 60 | Map<String, Method> settersForClassName = getterMap.get(className); |
664 | |
|
665 | 60 | if (settersForClassName != null) |
666 | |
{ |
667 | 60 | Method setter = pd.getWriteMethod(); |
668 | 60 | if (setter != null) |
669 | |
{ |
670 | 60 | settersForClassName.put(propName, setter); |
671 | |
} |
672 | |
} |
673 | 60 | } |
674 | |
} |
675 | 60 | return getter; |
676 | |
} |
677 | |
|
678 | |
|
679 | |
|
680 | |
|
681 | |
|
682 | |
@Override |
683 | |
public void configure(Configuration conf) throws ConfigurationException |
684 | |
{ |
685 | 20 | final Configuration xmlPaths = conf.getChild(XML_PATHS, false); |
686 | |
|
687 | 20 | xmlPathes = new ArrayList<String>(); |
688 | |
|
689 | 20 | if (xmlPaths == null) |
690 | |
{ |
691 | 0 | xmlPathes.add(XML_PATH_DEFAULT); |
692 | |
} |
693 | |
else |
694 | |
{ |
695 | 20 | Configuration[] nameVal = xmlPaths.getChildren(); |
696 | 60 | for (int i = 0; i < nameVal.length; i++) |
697 | |
{ |
698 | 40 | String val = nameVal[i].getValue(); |
699 | 40 | xmlPathes.add(val); |
700 | |
} |
701 | |
} |
702 | |
|
703 | 20 | serialDataPath = conf.getChild(SERIAL_XML, false).getValue(SERIAL_XML_DEFAULT); |
704 | |
|
705 | 20 | if (!serialDataPath.equalsIgnoreCase("none")) |
706 | |
{ |
707 | 20 | serialDataPath = new File(applicationRoot, serialDataPath).getAbsolutePath(); |
708 | |
} |
709 | |
else |
710 | |
{ |
711 | 0 | serialDataPath = null; |
712 | |
} |
713 | |
|
714 | 20 | getLogger().debug("Path for serializing: " + serialDataPath); |
715 | 20 | } |
716 | |
|
717 | |
|
718 | |
|
719 | |
|
720 | |
|
721 | |
|
722 | |
|
723 | |
|
724 | |
@Override |
725 | |
public void initialize() throws Exception |
726 | |
{ |
727 | 20 | Map<AppData, File> appDataElements = null; |
728 | |
|
729 | 20 | groupNames = new HashMap<String, AppData>(); |
730 | 20 | groupKeyMap = new HashMap<String, String>(); |
731 | 20 | groupNameMap = new HashMap<String, String>(); |
732 | 20 | getterMap = new HashMap<String, Map<String,Method>>(); |
733 | 20 | setterMap = new HashMap<String, Map<String,Method>>(); |
734 | 20 | keyedPools = new HashMap<AppData, KeyedObjectPool<String, Group>>(); |
735 | |
|
736 | 20 | Set<File> xmlFiles = new HashSet<File>(); |
737 | |
|
738 | 20 | long timeStamp = 0; |
739 | |
|
740 | 20 | for (String xmlPath : xmlPathes) |
741 | |
{ |
742 | |
|
743 | 40 | File xmlFile = new File(applicationRoot, xmlPath).getAbsoluteFile(); |
744 | |
|
745 | 40 | getLogger().debug("Path for XML File: " + xmlFile); |
746 | |
|
747 | 40 | if (!xmlFile.canRead()) |
748 | |
{ |
749 | 0 | String READ_ERR = "Could not read input file with path " |
750 | |
+ xmlPath + ". Looking for file " + xmlFile; |
751 | |
|
752 | 0 | getLogger().error(READ_ERR); |
753 | 0 | throw new Exception(READ_ERR); |
754 | |
} |
755 | |
|
756 | 40 | xmlFiles.add(xmlFile); |
757 | |
|
758 | 40 | getLogger().debug("Added " + xmlPath + " as File to parse"); |
759 | |
|
760 | |
|
761 | |
|
762 | |
|
763 | 40 | timeStamp = xmlFile.lastModified() > timeStamp ? xmlFile |
764 | 20 | .lastModified() : timeStamp; |
765 | 40 | } |
766 | |
|
767 | 20 | Map<AppData, File> serializedMap = loadSerialized(serialDataPath, timeStamp); |
768 | |
|
769 | 20 | if (serializedMap != null) |
770 | |
{ |
771 | |
|
772 | 19 | appDataElements = serializedMap; |
773 | 19 | getLogger().debug("Using the serialized map"); |
774 | |
} |
775 | |
else |
776 | |
{ |
777 | 1 | long timer = System.currentTimeMillis(); |
778 | |
|
779 | |
|
780 | 1 | JAXBContext jaxb = JAXBContext.newInstance(AppData.class); |
781 | 1 | Unmarshaller um = jaxb.createUnmarshaller(); |
782 | |
|
783 | |
|
784 | 1 | um.setEventHandler(new DefaultValidationEventHandler()); |
785 | |
|
786 | |
|
787 | 1 | Listener logEnabledListener = new AvalonLogEnabledListener(); |
788 | 1 | um.setListener(logEnabledListener); |
789 | |
|
790 | 1 | URL schemaURL = getClass().getResource("/intake.xsd"); |
791 | 1 | SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); |
792 | 1 | um.setSchema(schemaFactory.newSchema(schemaURL)); |
793 | 1 | appDataElements = new HashMap<AppData, File>(); |
794 | |
|
795 | 1 | for (File xmlFile : xmlFiles) |
796 | |
{ |
797 | 2 | getLogger().debug("Now parsing: " + xmlFile); |
798 | 2 | FileInputStream fis = null; |
799 | |
try |
800 | |
{ |
801 | 2 | fis = new FileInputStream(xmlFile); |
802 | 2 | AppData appData = (AppData) um.unmarshal(fis); |
803 | |
|
804 | 2 | appDataElements.put(appData, xmlFile); |
805 | 2 | getLogger().debug("Saving AppData for " + xmlFile); |
806 | |
} |
807 | |
finally |
808 | |
{ |
809 | 2 | if (fis != null) |
810 | |
{ |
811 | |
try |
812 | |
{ |
813 | 2 | fis.close(); |
814 | |
} |
815 | 0 | catch (IOException e) |
816 | |
{ |
817 | 0 | getLogger().warn("Could not close file " + xmlFile); |
818 | 2 | } |
819 | |
} |
820 | 0 | } |
821 | 2 | } |
822 | |
|
823 | 1 | getLogger().debug("Parsing took " + (System.currentTimeMillis() - timer)); |
824 | 1 | saveSerialized(serialDataPath, appDataElements); |
825 | |
} |
826 | |
|
827 | 20 | int counter = 0; |
828 | |
AppData appData; |
829 | |
File dataFile; |
830 | 20 | for ( Entry<AppData, File> entry : appDataElements.entrySet() ) |
831 | |
{ |
832 | |
|
833 | 40 | appData = entry.getKey(); |
834 | 40 | dataFile = entry.getValue(); |
835 | |
|
836 | 40 | int maxPooledGroups = 0; |
837 | 40 | List<Group> glist = appData.getGroups(); |
838 | |
|
839 | 40 | String groupPrefix = appData.getGroupPrefix(); |
840 | |
|
841 | 40 | for (ListIterator<Group> i = glist.listIterator(glist.size()); i.hasPrevious();) |
842 | |
{ |
843 | 120 | Group g = i.previous(); |
844 | 120 | String groupName = g.getIntakeGroupName(); |
845 | |
|
846 | 120 | boolean registerUnqualified = registerGroup(groupName, g, appData, true); |
847 | |
|
848 | 120 | if (!registerUnqualified) |
849 | |
{ |
850 | 0 | getLogger().info( |
851 | |
"Ignored redefinition of Group " + groupName |
852 | 0 | + " or Key " + g.getGID() + " from " |
853 | |
+ dataFile); |
854 | |
} |
855 | |
|
856 | 120 | if (groupPrefix != null) |
857 | |
{ |
858 | 0 | StringBuilder qualifiedName = new StringBuilder(); |
859 | 0 | qualifiedName.append(groupPrefix).append(':').append(groupName); |
860 | |
|
861 | |
|
862 | |
|
863 | |
|
864 | |
|
865 | |
|
866 | |
|
867 | 0 | if (!registerGroup(qualifiedName.toString(), g, |
868 | |
appData, !registerUnqualified)) |
869 | |
{ |
870 | 0 | getLogger().error( |
871 | |
"Could not register fully qualified name " |
872 | |
+ qualifiedName |
873 | |
+ ", maybe two XML files have the same prefix. Ignoring it."); |
874 | |
} |
875 | |
} |
876 | |
|
877 | |
|
878 | 120 | for (Field<?> f : g.getFields()) |
879 | |
{ |
880 | 560 | f.initGetterAndSetter(); |
881 | 560 | } |
882 | |
|
883 | 120 | maxPooledGroups = Math.max(maxPooledGroups, g.getPoolCapacity()); |
884 | 120 | } |
885 | |
|
886 | 40 | KeyedPooledObjectFactory<String, Group> factory = |
887 | |
new Group.GroupFactory(appData); |
888 | |
|
889 | 40 | GenericKeyedObjectPoolConfig<Group> poolConfig = new GenericKeyedObjectPoolConfig<Group>(); |
890 | 40 | poolConfig.setMaxTotalPerKey(maxPooledGroups); |
891 | 40 | poolConfig.setJmxEnabled(true); |
892 | 40 | poolConfig.setJmxNamePrefix("fulcrum-intake-pool-" + counter++); |
893 | |
|
894 | 40 | keyedPools.put(appData, |
895 | |
new GenericKeyedObjectPool<String, Group>(factory, poolConfig)); |
896 | 40 | } |
897 | |
|
898 | 20 | if (getLogger().isInfoEnabled()) |
899 | |
{ |
900 | 20 | getLogger().info("Intake Service is initialized now."); |
901 | |
} |
902 | 20 | } |
903 | |
|
904 | |
|
905 | |
|
906 | |
|
907 | |
|
908 | |
|
909 | |
|
910 | |
|
911 | |
|
912 | |
|
913 | |
@Override |
914 | |
public void contextualize(Context context) throws ContextException |
915 | |
{ |
916 | 20 | this.applicationRoot = context.get("urn:avalon:home").toString(); |
917 | 20 | } |
918 | |
|
919 | |
|
920 | |
|
921 | |
|
922 | |
|
923 | |
|
924 | |
|
925 | |
|
926 | |
|
927 | |
|
928 | |
|
929 | |
@Override |
930 | |
public void service(ServiceManager manager) throws ServiceException |
931 | |
{ |
932 | 20 | IntakeServiceFacade.setIntakeService(this); |
933 | 20 | } |
934 | |
} |