comparison artifact-database/src/main/java/org/dive4elements/artifactdatabase/FactoryBootstrap.java @ 473:d0ac790a6c89 dive4elements-move

Moved directories to org.dive4elements
author Sascha L. Teichmann <teichmann@intevation.de>
date Thu, 25 Apr 2013 10:57:18 +0200
parents artifact-database/src/main/java/de/intevation/artifactdatabase/FactoryBootstrap.java@ddfaf255bb40
children 415df0fc4fa1
comparison
equal deleted inserted replaced
472:783cc1b6b615 473:d0ac790a6c89
1 /*
2 * Copyright (c) 2010 by Intevation GmbH
3 *
4 * This program is free software under the LGPL (>=v2.1)
5 * Read the file LGPL.txt coming with the software for details
6 * or visit http://www.gnu.org/licenses/ if it does not exist.
7 */
8
9 package de.intevation.artifactdatabase;
10
11 import de.intevation.artifacts.common.utils.Config;
12
13 import de.intevation.artifacts.ArtifactCollectionFactory;
14 import de.intevation.artifacts.ArtifactContextFactory;
15 import de.intevation.artifacts.ArtifactFactory;
16 import de.intevation.artifacts.CallContext;
17 import de.intevation.artifacts.GlobalContext;
18 import de.intevation.artifacts.Hook;
19 import de.intevation.artifacts.ServiceFactory;
20 import de.intevation.artifacts.UserFactory;
21
22 import de.intevation.artifacts.common.utils.StringUtils;
23
24 import de.intevation.artifactdatabase.rest.HTTPServer;
25
26 import java.util.ArrayList;
27 import java.util.List;
28
29 import org.apache.log4j.Logger;
30
31 import org.w3c.dom.Document;
32 import org.w3c.dom.Node;
33 import org.w3c.dom.NodeList;
34
35 /**
36 * Bootstrap facility for the global context and the artifact factories.
37 *
38 * @author <a href="mailto:sascha.teichmann@intevation.de">Sascha L. Teichmann</a>
39 */
40 public class FactoryBootstrap
41 {
42 private static Logger logger = Logger.getLogger(FactoryBootstrap.class);
43
44 /**
45 * XPath to figure out the class name of the context factory from
46 * the global configuration.
47 */
48 public static final String CONTEXT_FACTORY =
49 "/artifact-database/factories/context-factory/text()";
50
51 /**
52 * The name of the default context factory.
53 */
54 public static final String DEFAULT_CONTEXT_FACTORY =
55 "de.intevation.artifactdatabase.DefaultArtifactContextFactory";
56
57 /**
58 * XPath to figure out the names of the artifact factories from
59 * the global configuration to be exposed by the artifact database.
60 */
61 public static final String ARTIFACT_FACTORIES =
62 "/artifact-database/factories/artifact-factories/artifact-factory";
63
64 /**
65 * XPath to figure out the names of the service factories from
66 * the global configuration to build the services offered by the
67 * artifact database.
68 */
69 public static final String SERVICE_FACTORIES =
70 "/artifact-database/factories/service-factories/service-factory";
71
72 /**
73 * XPath to figure out the class name of the user factory from global
74 * configuration.
75 */
76 public static final String USER_FACTORY =
77 "/artifact-database/factories/user-factory";
78
79 /**
80 * The name of the default user factory.
81 */
82 public static final String DEFAULT_USER_FACTORY =
83 "de.intevation.artifactdatabase.DefaultUserFactory";
84
85 /**
86 * XPath to figure out the class name of the collection factory from global
87 * configuration.
88 */
89 public static final String COLLECTION_FACTORY =
90 "/artifact-database/factories/collection-factory";
91
92 /**
93 * The name of the default user factory.
94 */
95 public static final String DEFAULT_COLLECTION_FACTORY =
96 "de.intevation.artifactdatabase.DefaultArtifactCollectionFactory";
97
98 /**
99 * XPath to figure out the secret used to sign the artifact exports
100 * made by the artfifact database server.
101 */
102 public static final String EXPORT_SECRET =
103 "/artifact-database/export-secret/text()";
104
105 /**
106 * XPAth that points to a configuration node for a CallContext.Listener.
107 */
108 public static final String CALLCONTEXT_LISTENER =
109 "/artifact-database/callcontext-listener";
110
111 /**
112 * XPath that points to configuration nodes for hooks.
113 */
114 public static final String HOOKS =
115 "/artifact-database/hooks/hook";
116
117 public static final String HTTP_SERVER =
118 "/artifact-database/rest-server/http-server/text()";
119
120 public static final String DEFAULT_HTTP_SERVER =
121 "de.intevation.artifactdatabase.rest.Standalone";
122
123 public static final String LIFETIME_LISTENERS =
124 "/artifact-database/lifetime-listeners/listener";
125
126 public static final String BACKEND_LISTENERS =
127 "/artifact-database/backend-listeners/listener";
128
129 /**
130 * Default export signing secret.
131 * <strong>PLEASE CHANGE THE SECRET VIA THE XPATH EXPORT_SECRET
132 * IN THE CONFIGURATION.</strong>.
133 */
134 public static final String DEFAULT_EXPORT_SECRET =
135 "!!!CHANGE ME! I'M NO SECRET!!!";
136
137 /**
138 * Reference to the global context build by the global context factory.
139 */
140 protected GlobalContext context;
141
142 /**
143 * List of the artifact factories to be exposed by the
144 * artifact database.
145 */
146 protected ArtifactFactory [] artifactFactories;
147
148 /**
149 * List of service factories which creates services that are
150 * exposed by the artifact database.
151 */
152 protected ServiceFactory [] serviceFactories;
153
154 /**
155 * The factory that is used to create and list users.
156 */
157 protected UserFactory userFactory;
158
159 /**
160 * The factory that is used to create new artifact collections.
161 */
162 protected ArtifactCollectionFactory collectionFactory;
163
164 /**
165 * The CallContext.Listener.
166 */
167 protected CallContext.Listener callContextListener;
168
169 protected List<Hook> postFeedHooks;
170
171 protected List<Hook> postAdvanceHooks;
172
173 protected List<Hook> postDescribeHooks;
174
175 protected List<LifetimeListener> lifetimeListeners;
176
177 protected List<BackendListener> backendListeners;
178
179 /**
180 * byte array holding the export signing secret.
181 */
182 protected byte [] exportSecret;
183
184 protected HTTPServer httpServer;
185
186
187 /**
188 * Default constructor
189 */
190 public FactoryBootstrap() {
191 }
192
193 void buildContext() {
194 String className = Config.getStringXPath(
195 CONTEXT_FACTORY, DEFAULT_CONTEXT_FACTORY);
196
197 ArtifactContextFactory factory = null;
198
199 try {
200 Class clazz = Class.forName(className);
201 factory = (ArtifactContextFactory)clazz.newInstance();
202 }
203 catch (ClassNotFoundException cnfe) {
204 logger.error(cnfe.getLocalizedMessage(), cnfe);
205 }
206 catch (InstantiationException ie) {
207 logger.error(ie.getLocalizedMessage(), ie);
208 }
209 catch (ClassCastException cce) {
210 logger.error(cce.getLocalizedMessage(), cce);
211 }
212 catch (IllegalAccessException iae) {
213 logger.error(iae.getLocalizedMessage(), iae);
214 }
215
216 if (factory == null) {
217 factory = new DefaultArtifactContextFactory();
218 }
219
220 logger.info("Using class '" + factory.getClass().getName()
221 + "' for context creation.");
222
223 context = factory.createArtifactContext(Config.getConfig());
224 }
225
226
227 /**
228 * Scans the global configuration to load the configured collection factory
229 * and sets it up.
230 */
231 protected void loadCollectionFactory() {
232
233 logger.info("loading collection factory.");
234
235 Node factory = Config.getNodeXPath(COLLECTION_FACTORY);
236
237 String className = Config.getStringXPath(
238 factory, "text()", DEFAULT_COLLECTION_FACTORY);
239
240 try {
241 Class clazz = Class.forName(className);
242 collectionFactory = (ArtifactCollectionFactory) clazz.newInstance();
243
244 collectionFactory.setup(Config.getConfig(), factory);
245 }
246 catch (ClassNotFoundException cnfe) {
247 logger.error(cnfe.getLocalizedMessage(), cnfe);
248 }
249 catch (InstantiationException ie) {
250 logger.error(ie.getLocalizedMessage(), ie);
251 }
252 catch (ClassCastException cce) {
253 logger.error(cce.getLocalizedMessage(), cce);
254 }
255 catch (IllegalAccessException iae) {
256 logger.error(iae.getLocalizedMessage(), iae);
257 }
258 }
259
260 /**
261 * Scans the global configuration to load the configured
262 * artifact factories and sets them up.
263 */
264 protected void loadArtifactFactories() {
265
266 logger.info("loading artifact factories");
267
268 ArrayList loadedFactories = new ArrayList();
269
270 NodeList nodes = Config.getNodeSetXPath(ARTIFACT_FACTORIES);
271
272 if (nodes == null) {
273 logger.warn("No factories found");
274 }
275
276 Document config = Config.getConfig();
277
278 for (int i = 0, N = nodes != null ? nodes.getLength() : 0; i < N; ++i) {
279 String className = nodes.item(i).getTextContent().trim();
280
281 ArtifactFactory factory = null;
282
283 try {
284 Class clazz = Class.forName(className);
285 factory = (ArtifactFactory)clazz.newInstance();
286 }
287 catch (ClassNotFoundException cnfe) {
288 logger.error(cnfe.getLocalizedMessage(), cnfe);
289 }
290 catch (InstantiationException ie) {
291 logger.error(ie.getLocalizedMessage(), ie);
292 }
293 catch (ClassCastException cce) {
294 logger.error(cce.getLocalizedMessage(), cce);
295 }
296 catch (IllegalAccessException iae) {
297 logger.error(iae.getLocalizedMessage(), iae);
298 }
299
300 if (factory != null) {
301 factory.setup(config, nodes.item(i));
302 loadedFactories.add(factory);
303 logger.info("Registering '"
304 + factory.getName() + "' as artifact factory.");
305 }
306 }
307
308 artifactFactories = (ArtifactFactory [])loadedFactories.toArray(
309 new ArtifactFactory[loadedFactories.size()]);
310 }
311
312 /**
313 * Scans the global configuration for the configured service factories
314 * and sets them up.
315 */
316 protected void loadServiceFactories() {
317
318 logger.info("loading service factories");
319
320 ArrayList loadedFactories = new ArrayList();
321
322 NodeList nodes = Config.getNodeSetXPath(SERVICE_FACTORIES);
323
324 if (nodes == null) {
325 logger.warn("No factories found");
326 }
327
328 Document config = Config.getConfig();
329
330 for (int i = 0, N = nodes != null ? nodes.getLength() : 0; i < N; ++i) {
331 String className = nodes.item(i).getTextContent().trim();
332
333 ServiceFactory factory = null;
334
335 try {
336 Class clazz = Class.forName(className);
337 factory = (ServiceFactory)clazz.newInstance();
338 }
339 catch (ClassNotFoundException cnfe) {
340 logger.error(cnfe.getLocalizedMessage(), cnfe);
341 }
342 catch (InstantiationException ie) {
343 logger.error(ie.getLocalizedMessage(), ie);
344 }
345 catch (ClassCastException cce) {
346 logger.error(cce.getLocalizedMessage(), cce);
347 }
348 catch (IllegalAccessException iae) {
349 logger.error(iae.getLocalizedMessage(), iae);
350 }
351
352 if (factory != null) {
353 factory.setup(config, nodes.item(i));
354 loadedFactories.add(factory);
355 logger.info( "Registering '" + factory.getName()
356 + "' as service factory.");
357 }
358 }
359
360 serviceFactories = (ServiceFactory [])loadedFactories.toArray(
361 new ServiceFactory[loadedFactories.size()]);
362 }
363
364
365 /**
366 * Scans the global configuration for the configured user factory.
367 */
368 protected void loadUserFactory() {
369 logger.info("loading user factory");
370
371 Node factory = Config.getNodeXPath(USER_FACTORY);
372
373 String className = Config.getStringXPath(
374 factory, "text()", DEFAULT_USER_FACTORY);
375
376 try {
377 Class clazz = Class.forName(className);
378 userFactory = (UserFactory) clazz.newInstance();
379
380 userFactory.setup(Config.getConfig(), factory);
381 }
382 catch (ClassNotFoundException cnfe) {
383 logger.error(cnfe.getLocalizedMessage(), cnfe);
384 }
385 catch (InstantiationException ie) {
386 logger.error(ie.getLocalizedMessage(), ie);
387 }
388 catch (ClassCastException cce) {
389 logger.error(cce.getLocalizedMessage(), cce);
390 }
391 catch (IllegalAccessException iae) {
392 logger.error(iae.getLocalizedMessage(), iae);
393 }
394 }
395
396
397 protected void loadCallContextListener() {
398 logger.info("loading CallContext.Listener");
399
400 Node listener = Config.getNodeXPath(CALLCONTEXT_LISTENER);
401
402 if (listener == null) {
403 return;
404 }
405
406 String className = Config.getStringXPath(listener, "text()");
407
408 try {
409 Class clazz = Class.forName(className);
410 callContextListener = (CallContext.Listener) clazz.newInstance();
411
412 callContextListener.setup(Config.getConfig(), listener);
413 }
414 catch (ClassNotFoundException cnfe) {
415 logger.error(cnfe.getLocalizedMessage(), cnfe);
416 }
417 catch (InstantiationException ie) {
418 logger.error(ie.getLocalizedMessage(), ie);
419 }
420 catch (ClassCastException cce) {
421 logger.error(cce.getLocalizedMessage(), cce);
422 }
423 catch (IllegalAccessException iae) {
424 logger.error(iae.getLocalizedMessage(), iae);
425 }
426 }
427
428 protected void loadHTTPServer() {
429 logger.info("loading HTTPServer");
430
431 String className = Config.getStringXPath(
432 HTTP_SERVER, DEFAULT_HTTP_SERVER);
433
434 logger.info("using HTTP server: " + className);
435
436 try {
437 Class clazz = Class.forName(className);
438 httpServer = (HTTPServer)clazz.newInstance();
439
440 httpServer.setup(Config.getConfig());
441 }
442 catch (ClassNotFoundException cnfe) {
443 logger.error(cnfe.getLocalizedMessage(), cnfe);
444 }
445 catch (InstantiationException ie) {
446 logger.error(ie.getLocalizedMessage(), ie);
447 }
448 catch (ClassCastException cce) {
449 logger.error(cce.getLocalizedMessage(), cce);
450 }
451 catch (IllegalAccessException iae) {
452 logger.error(iae.getLocalizedMessage(), iae);
453 }
454 }
455
456 protected void loadLifetimeListeners() {
457 logger.info("loading lifetime listeners");
458
459 NodeList nodes = Config.getNodeSetXPath(LIFETIME_LISTENERS);
460
461 if (nodes == null) {
462 logger.debug("no lifetime listeners configure");
463 return;
464 }
465
466 List<LifetimeListener> ltls = new ArrayList<LifetimeListener>();
467
468 for (int i = 0, N = nodes.getLength(); i < N; ++i) {
469 Node node = nodes.item(i);
470 String className = node.getTextContent();
471 if (className == null
472 || (className = className.trim()).length() == 0) {
473 continue;
474 }
475 try {
476 Class clazz = Class.forName(className);
477 LifetimeListener listener =
478 (LifetimeListener)clazz.newInstance();
479
480 listener.setup(Config.getConfig());
481
482 ltls.add(listener);
483 }
484 catch (ClassNotFoundException cnfe) {
485 logger.error(cnfe.getLocalizedMessage(), cnfe);
486 }
487 catch (InstantiationException ie) {
488 logger.error(ie.getLocalizedMessage(), ie);
489 }
490 catch (ClassCastException cce) {
491 logger.error(cce.getLocalizedMessage(), cce);
492 }
493 catch (IllegalAccessException iae) {
494 logger.error(iae.getLocalizedMessage(), iae);
495 }
496 }
497
498 lifetimeListeners = ltls;
499 }
500
501 protected void loadBackendListeners() {
502 logger.info("loading backend listeners");
503
504 NodeList nodes = Config.getNodeSetXPath(BACKEND_LISTENERS);
505
506 if (nodes == null) {
507 logger.debug("no backend listeners configure");
508 return;
509 }
510
511 List<BackendListener> bls = new ArrayList<BackendListener>();
512
513 for (int i = 0, N = nodes.getLength(); i < N; ++i) {
514 Node node = nodes.item(i);
515 String className = node.getTextContent();
516 if (className == null
517 || (className = className.trim()).length() == 0) {
518 continue;
519 }
520 try {
521 Class clazz = Class.forName(className);
522 BackendListener listener =
523 (BackendListener)clazz.newInstance();
524
525 bls.add(listener);
526 }
527 catch (ClassNotFoundException cnfe) {
528 logger.error(cnfe.getLocalizedMessage(), cnfe);
529 }
530 catch (InstantiationException ie) {
531 logger.error(ie.getLocalizedMessage(), ie);
532 }
533 catch (ClassCastException cce) {
534 logger.error(cce.getLocalizedMessage(), cce);
535 }
536 catch (IllegalAccessException iae) {
537 logger.error(iae.getLocalizedMessage(), iae);
538 }
539 }
540
541 backendListeners = bls;
542 }
543
544 protected void loadHooks() {
545 logger.info("loading hooks");
546
547 postFeedHooks = new ArrayList<Hook>();
548 postAdvanceHooks = new ArrayList<Hook>();
549 postDescribeHooks = new ArrayList<Hook>();
550
551 NodeList nodes = Config.getNodeSetXPath(HOOKS);
552
553 if (nodes == null) {
554 logger.info("No hooks found");
555 return;
556 }
557
558 for (int i = 0, len = nodes.getLength(); i < len; i++) {
559 Node cfg = nodes.item(i);
560 String applies = Config.getStringXPath(cfg, "@applies");
561
562 if (applies == null || applies.length() == 0) {
563 continue;
564 }
565
566 Hook hook = loadHook(cfg);
567 String[] apply = applies.split(",");
568
569 for (String a: apply) {
570 a = a.trim().toLowerCase();
571
572 if (a.equals("post-feed")) {
573 postFeedHooks.add(hook);
574 }
575 else if (a.equals("post-advance")) {
576 postAdvanceHooks.add(hook);
577 }
578 else if (a.equals("post-describe")) {
579 postDescribeHooks.add(hook);
580 }
581 }
582 }
583 }
584
585 protected Hook loadHook(Node hookCfg) {
586 if (hookCfg == null) {
587 return null;
588 }
589
590 Hook hook = null;
591
592 String className = Config.getStringXPath(hookCfg, "@class");
593
594 try {
595 Class clazz = Class.forName(className);
596 hook = (Hook) clazz.newInstance();
597
598 hook.setup(hookCfg);
599 }
600 catch (ClassNotFoundException cnfe) {
601 logger.error(cnfe.getLocalizedMessage(), cnfe);
602 }
603 catch (InstantiationException ie) {
604 logger.error(ie.getLocalizedMessage(), ie);
605 }
606 catch (ClassCastException cce) {
607 logger.error(cce.getLocalizedMessage(), cce);
608 }
609 catch (IllegalAccessException iae) {
610 logger.error(iae.getLocalizedMessage(), iae);
611 }
612
613 return hook;
614 }
615
616 /**
617 * Fetches the export signing secret from the global configuration.
618 * If none is found if defaults to the DEFAULT_EXORT_SECRET which
619 * is insecure.
620 */
621 protected void setupExportSecret() {
622 String secret = Config.getStringXPath(EXPORT_SECRET);
623
624 if (secret == null) {
625 logger.warn("NO EXPORT SECRET SET! USING INSECURE DEFAULT!");
626 secret = DEFAULT_EXPORT_SECRET;
627 }
628
629 exportSecret = StringUtils.getUTF8Bytes(secret);
630 }
631
632 /**
633 * Loads all the dynamic classes configured by the global configuration.
634 */
635 public void boot() {
636 setupExportSecret();
637 buildContext();
638 loadCollectionFactory();
639 loadArtifactFactories();
640 loadServiceFactories();
641 loadUserFactory();
642 loadCallContextListener();
643 loadHTTPServer();
644 loadHooks();
645 loadLifetimeListeners();
646 loadBackendListeners();
647 }
648
649 /**
650 * Returns the artifact collection factory.
651 *
652 * @return the artifact collection factory.
653 */
654 public ArtifactCollectionFactory getArtifactCollectionFactory() {
655 return collectionFactory;
656 }
657
658 /**
659 * Returns the list of ready to use artifact factories.
660 * @return The list of artifact factories.
661 */
662 public ArtifactFactory [] getArtifactFactories() {
663 return artifactFactories;
664 }
665
666 /**
667 * Returns the ready to use service factories.
668 * @return The list of service factories.
669 */
670 public ServiceFactory [] getServiceFactories() {
671 return serviceFactories;
672 }
673
674 /**
675 * Returns the user factory.
676 *
677 * @return the user factory.
678 */
679 public UserFactory getUserFactory() {
680 return userFactory;
681 }
682
683 /**
684 * Returns the global context created by the global context factory.
685 * @return The global context.
686 */
687 public GlobalContext getContext() {
688 return context;
689 }
690
691 /**
692 * Returns the signing secret to be used when ex- and importing
693 * artifacts from and into the artifact database.
694 * @return the byte array containg the signing secret.
695 */
696 public byte [] getExportSecret() {
697 return exportSecret;
698 }
699
700 /**
701 * Returns a CallContext.Listener if configured or null.
702 *
703 * @return a CallContext.Listener.
704 */
705 public CallContext.Listener getCallContextListener() {
706 return callContextListener;
707 }
708
709 public List<Hook> getPostFeedHooks() {
710 return postFeedHooks;
711 }
712
713 public List<Hook> getPostAdvanceHooks() {
714 return postAdvanceHooks;
715 }
716
717 public List<Hook> getPostDescribeHooks() {
718 return postDescribeHooks;
719 }
720
721 public HTTPServer getHTTPServer() {
722 return httpServer;
723 }
724
725 public List<LifetimeListener> getLifetimeListeners() {
726 return lifetimeListeners;
727 }
728
729 public List<BackendListener> getBackendListeners() {
730 return backendListeners;
731 }
732 }
733 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org