1
2
3
4
5
6
7
8
9
10
11
12
13 package org.abstracthorizon.extend.server.deployment;
14
15 import java.net.URI;
16 import java.util.Collection;
17 import java.util.HashSet;
18 import java.util.Iterator;
19 import java.util.LinkedHashMap;
20 import java.util.LinkedHashSet;
21 import java.util.Map;
22 import java.util.Set;
23
24 import org.abstracthorizon.extend.server.deployment.support.ProvisionalModule;
25 import org.abstracthorizon.extend.server.support.EnhancedMap;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29
30
31
32
33
34 public class DeploymentManagerImpl implements DeploymentManager {
35
36
37 private final Logger logger = LoggerFactory.getLogger(DeploymentManagerImpl.class);
38
39
40 protected ModuleLoaders<ModuleLoader> moduleLoaders = new ModuleLoaders<ModuleLoader>();
41
42
43 protected DeployedModules<ModuleId, Module> deployedModules = new DeployedModules<ModuleId, Module>();
44
45
46 public DeploymentManagerImpl() {
47 }
48
49
50
51
52
53
54 public boolean isDeployed(Module module) {
55
56
57 return deployedModules.containsValue(module);
58 }
59
60
61
62
63
64
65
66 public void deploy(ModuleId moduleId, Module module) {
67 Module old = deployedModules.get(moduleId);
68 if (old != module) {
69 long startedTime = 0;
70 if (logger.isDebugEnabled()) {
71 startedTime = System.currentTimeMillis();
72 logger.debug("Deploying module '" + moduleId + "' of class=" + module.getClass());
73 } else if (logger.isInfoEnabled()) {
74 logger.info("Deploying module '" + moduleId + "'");
75 }
76 if (old != null) {
77 if (!(old instanceof ProvisionalModule)) {
78 String errorMsg = "Module with id '" + moduleId + "' already exists; class=" + old.getClass() + ". Cannot deploy it.";
79 logger.error(errorMsg);
80 throw new RuntimeException(errorMsg);
81 }
82 deployedModules.remove(old);
83 }
84 deployedModules.put(moduleId, module);
85
86
87 if (old != null) {
88 if (logger.isDebugEnabled()) {
89 logger.debug("Updating references to this module from provisional module; id=" + moduleId + "'");
90 }
91 for (Module m : old.getDependsOn()) {
92 m.getDependOnThis().remove(old);
93 m.getDependOnThis().add(module);
94 }
95 for (Module m : old.getDependOnThis()) {
96 m.getDependsOn().remove(old);
97 m.getDependsOn().add(module);
98 }
99
100 module.getDependOnThis().addAll(old.getDependOnThis());
101 }
102
103 if (logger.isDebugEnabled()) {
104 logger.debug("Creating module '" + moduleId + "'.");
105 }
106 create(module);
107 if ((module.getState() == Module.CREATED) || (module.getState() == Module.WAITING_ON_CREATE)) {
108 start(module);
109 }
110 if (logger.isDebugEnabled()) {
111 logger.debug("Deployed module '" + moduleId + "' (" + Long.toString(System.currentTimeMillis() - startedTime) + "ms)");
112 }
113 }
114 }
115
116
117
118
119
120
121 public void undeploy(Module module) {
122 ModuleId moduleId = module.getModuleId();
123 if (logger.isInfoEnabled()) {
124 logger.info("Undeploying module '" + moduleId + "'.");
125 }
126 int state = module.getState();
127 if ((state == Module.STARTED) || (state == Module.WAITING_ON_CREATE_TO_START)) {
128 stop(module);
129 }
130 destroy(module);
131
132 deployedModules.remove(module);
133 if (logger.isInfoEnabled()) {
134 logger.info("Module '" + moduleId + "' is now undeployed.");
135 }
136 }
137
138
139
140
141
142
143 public void redeploy(Module module) {
144 ModuleId moduleId = module.getModuleId();
145 if (logger.isInfoEnabled()) {
146 logger.info("Redeploying module '" + moduleId + "'.");
147 }
148 if (!deployedModules.containsValue(module)) {
149 throw new RuntimeException("Module is not deployed");
150 }
151
152 Set<ModuleId> aliases = findAliases(module);
153 Iterator<ModuleId> it = aliases.iterator();
154 undeploy(module);
155 deploy(it.next(), module);
156 while (it.hasNext()) {
157 deployedModules.put(it.next(), module);
158 }
159 }
160
161
162
163
164
165
166 public Set<ModuleId> findAliases(Module module) {
167 Set<ModuleId> result = new HashSet<ModuleId>();
168 for (Map.Entry<ModuleId, Module> entry : deployedModules.entrySet()) {
169 if (entry.getValue().equals(module)) {
170 result.add(entry.getKey());
171 }
172 }
173 return result;
174 }
175
176
177
178
179
180 public void create(Module module) {
181 if (logger.isDebugEnabled()) {
182 logger.debug("Creating module '" + module.getModuleId() + "'.");
183 }
184 ClassLoader oldcl = Thread.currentThread().getContextClassLoader();
185 ClassLoader newcl = module.getClassLoader();
186 if (newcl != null) {
187 Thread.currentThread().setContextClassLoader(newcl);
188 }
189 try {
190 module.create();
191 } finally {
192 if (newcl != null) {
193 Thread.currentThread().setContextClassLoader(oldcl);
194 }
195 }
196 if (module.getState() == Module.CREATED) {
197 if (logger.isInfoEnabled()) {
198 logger.info("Created module '" + module.getModuleId() + "'.");
199 }
200 if (!module.getDependsOn().isEmpty()) {
201 if (logger.isDebugEnabled()) {
202 logger.debug("Creating dependent modules of module '" + module.getModuleId() + "'.");
203 }
204 for (Module m : module.getDependOnThis()) {
205 if (m.getState() == Module.WAITING_ON_CREATE) {
206 create(m);
207 }
208 if (m.getState() == Module.WAITING_ON_CREATE_TO_START) {
209 create(m);
210 if (m.getState() == Module.CREATED) {
211 m.setState(Module.WAITING_ON_START);
212 }
213 }
214 }
215 }
216 } else if ((module.getState() == Module.WAITING_ON_CREATE) || (module.getState() == Module.WAITING_ON_CREATE_TO_START)) {
217 if (logger.isDebugEnabled()) {
218 logger.debug("Creating module '" + module.getModuleId() + "' postponed until dependencies available: " + getUnsatisfiedDependenciesAsAList(module));
219 }
220 } else {
221 if (logger.isWarnEnabled()) {
222 logger.warn("Creating module '" + module.getModuleId() + "' failed.");
223 }
224 }
225 }
226
227
228
229
230
231 public void start(Module module) {
232 if (logger.isDebugEnabled()) {
233 logger.debug("Starting module '" + module.getModuleId() + "'.");
234 }
235 ClassLoader oldcl = Thread.currentThread().getContextClassLoader();
236 ClassLoader newcl = module.getClassLoader();
237 if (newcl != null) {
238 Thread.currentThread().setContextClassLoader(newcl);
239 }
240 try {
241 module.start();
242 } finally {
243 if (newcl != null) {
244 Thread.currentThread().setContextClassLoader(oldcl);
245 }
246 }
247 if (module.getState() == Module.STARTED) {
248 if (logger.isInfoEnabled()) {
249 logger.info("Started module '" + module.getModuleId() + "'.");
250 }
251 if (!module.getDependOnThis().isEmpty()) {
252 if (logger.isDebugEnabled()) {
253 logger.debug("Starting dependent modules of module '" + module.getModuleId() + "'.");
254 }
255 for (Module m : module.getDependOnThis()) {
256 if (m.getState() == Module.WAITING_ON_CREATE) {
257 create(m);
258 }
259 if (m.getState() == Module.WAITING_ON_CREATE_TO_START) {
260 create(m);
261 if (m.getState() == Module.CREATED) {
262 m.setState(Module.WAITING_ON_START);
263 }
264 }
265 if (m.getState() == Module.WAITING_ON_START) {
266 start(m);
267 }
268 }
269 }
270 } else if ((module.getState() == Module.WAITING_ON_START) || (module.getState() == Module.WAITING_ON_CREATE_TO_START)) {
271 if (logger.isDebugEnabled()) {
272 logger.debug("Starting module '" + module.getModuleId() + "' postponed until dependencies available: " + getUnsatisfiedDependenciesAsAList(module));
273 }
274 } else {
275 if (logger.isWarnEnabled()) {
276 logger.warn("Starting module '" + module.getModuleId() + "' failed.");
277 }
278 }
279 }
280
281
282
283
284
285 public void stop(Module module) {
286 if ((module.getState() == Module.STARTED) && !module.getDependOnThis().isEmpty()) {
287 if (logger.isDebugEnabled()) {
288 logger.debug("Stopping dependent modules of module '" + module.getModuleId() + "'.");
289 }
290 for (Module m : module.getDependOnThis()) {
291 if (m.getState() == Module.STARTED) {
292 stop(m);
293 if (m.getState() == Module.CREATED) {
294 m.setState(Module.WAITING_ON_START);
295 } else {
296 if (logger.isWarnEnabled()) {
297 logger.warn("Stopping module '" + module.getModuleId() + "' failed because of stopping of dependent module " + m.getModuleId() + " failed.");
298 }
299 }
300 }
301 if (m.getState() == Module.STARTED) {
302 throw new DeploymentException("Cannot stop module " + module.getModuleId() + " since dependent module " + m.getModuleId() + " in in illegal state " + ModuleUtil.stateAsString(m.getState()) + ".");
303 }
304 }
305 }
306 if (logger.isDebugEnabled()) {
307 logger.debug("Stopping module '" + module.getModuleId() + "'.");
308 }
309 ClassLoader oldcl = Thread.currentThread().getContextClassLoader();
310 ClassLoader newcl = module.getClassLoader();
311 if (newcl != null) {
312 Thread.currentThread().setContextClassLoader(newcl);
313 }
314 try {
315 module.stop();
316 } finally {
317 if (newcl != null) {
318 Thread.currentThread().setContextClassLoader(oldcl);
319 }
320 }
321 if (module.getState() != Module.STARTED) {
322 if (logger.isInfoEnabled()) {
323 logger.info("Stopped module '" + module.getModuleId() + "'.");
324 }
325 } else {
326 if (logger.isInfoEnabled()) {
327 logger.info("Stoping module '" + module.getModuleId() + "' failed.");
328 }
329 }
330 }
331
332
333
334
335
336 public void destroy(Module module) {
337 if ((module.getState() == Module.CREATED) && !module.getDependOnThis().isEmpty()) {
338 if (logger.isDebugEnabled()) {
339 logger.debug("Destroying dependent modules of module '" + module.getModuleId() + "'.");
340 }
341 for (Module m : module.getDependOnThis()) {
342 if (m.getState() == Module.CREATED) {
343 destroy(m);
344 if (m.getState() == Module.DEFINED) {
345 m.setState(Module.WAITING_ON_CREATE);
346 } else {
347 if (logger.isWarnEnabled()) {
348 logger.warn("Stopping module '" + module.getModuleId() + "' failed because of stopping of dependent module " + m.getModuleId() + " failed.");
349 }
350 return;
351 }
352 } else if (m.getState() == Module.WAITING_ON_START) {
353 destroy(m);
354 if (m.getState() == Module.DEFINED) {
355 m.setState(Module.WAITING_ON_CREATE_TO_START);
356 } else {
357 if (logger.isWarnEnabled()) {
358 logger.warn("Stopping module '" + module.getModuleId() + "' failed because of stopping of dependent module " + m.getModuleId() + " failed.");
359 }
360 return;
361 }
362 }
363 if ((m.getState() != Module.DEFINED) && (m.getState() != Module.WAITING_ON_CREATE_TO_START) && (m.getState() == Module.WAITING_ON_CREATE)) {
364 throw new DeploymentException("Cannot destroy module " + module.getModuleId() + " since dependent module " + m.getModuleId() + " in in illegal state " + ModuleUtil.stateAsString(m.getState()) + ".");
365 }
366 }
367 }
368 if (logger.isDebugEnabled()) {
369 logger.debug("Destroying module '" + module.getModuleId() + "'.");
370 }
371 ClassLoader oldcl = Thread.currentThread().getContextClassLoader();
372 ClassLoader newcl = module.getClassLoader();
373 if (newcl != null) {
374 Thread.currentThread().setContextClassLoader(newcl);
375 }
376 try {
377 module.destroy();
378 } finally {
379 if (newcl != null) {
380 Thread.currentThread().setContextClassLoader(oldcl);
381 }
382 }
383 if (module.getState() == Module.DEFINED) {
384 if (logger.isInfoEnabled()) {
385 logger.info("Destroyed module '" + module.getModuleId() + "'.");
386 }
387 } else {
388 if (logger.isInfoEnabled()) {
389 logger.info("Destroying module '" + module.getModuleId() + "' failed.");
390 }
391 }
392 }
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417 public EnhancedMap<ModuleId, Module> getDeployedModules() {
418 return deployedModules;
419 }
420
421
422
423
424
425
426 public boolean canLoad(URI url) {
427 for (ModuleLoader loader : moduleLoaders) {
428 if (loader.canLoad(url)) {
429 return true;
430 }
431 }
432 return false;
433 }
434
435
436
437
438
439
440 public ModuleId toModuleId(URI uri) {
441 for (ModuleLoader loader : moduleLoaders) {
442 if (loader.canLoad(uri)) {
443 ModuleId moduleId = loader.toModuleId(uri);
444 if (moduleId != null) {
445 return moduleId;
446 }
447 }
448 }
449 return null;
450 }
451
452
453
454
455
456
457
458
459
460
461 public Module load(URI uri) {
462 Module module = null;
463 for (ModuleLoader loader : moduleLoaders) {
464 if (loader.canLoad(uri)) {
465 module = loader.load(uri);
466 return module;
467 }
468 }
469
470
471
472
473 return module;
474 }
475
476
477
478
479
480
481
482
483
484
485 public Module loadAs(URI uri, ModuleId moduleId) {
486 Module module = null;
487 for (ModuleLoader loader : moduleLoaders) {
488 if (loader.canLoad(uri)) {
489 module = loader.loadAs(uri, moduleId);
490 return module;
491 }
492 }
493
494
495
496
497 return module;
498 }
499
500
501
502
503
504
505 public Module loadAndDeploy(URI uri) {
506 ModuleId moduleId = toModuleId(uri);
507 Module module = null;
508 if (moduleId != null) {
509 module = getDeployedModules().get(moduleId);
510 }
511 if (module == null) {
512 module = load(uri);
513 if (module != null) {
514 if (!(module instanceof ProvisionalModule)) {
515 if (!getDeployedModules().containsValue(module)) {
516 deploy(module.getModuleId(), module);
517 } else if (!getDeployedModules().containsKey(module.getModuleId())) {
518 getDeployedModules().put(module.getModuleId(), module);
519 } else {
520 logger.debug("Module " + module.getModuleId() + " at " + uri + " already exists");
521 }
522 }
523 } else {
524
525 }
526 }
527 return module;
528 }
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545 public void redeploy(ModuleId moduleId) {
546 Module module = getDeployedModules().get(moduleId);
547 undeploy(module);
548 deploy(moduleId, module);
549 }
550
551
552
553
554
555 public Set<ModuleLoader> getModuleLoaders() {
556 return moduleLoaders;
557 }
558
559
560
561
562
563 public void setModuleLoaders(Set<ModuleLoader> moduleLoaders) {
564 this.moduleLoaders.clear();
565 this.moduleLoaders.addAll(moduleLoaders);
566 }
567
568
569
570
571
572
573 protected void tryToDeployUnknown() {
574 Map<ModuleId, Module> toBeDeployed = new LinkedHashMap<ModuleId, Module>();
575 Iterator<Module> it = deployedModules.values().iterator();
576 while (it.hasNext()) {
577 Module module = it.next();
578 if (module instanceof ProvisionalModule) {
579 URI uri = ((ProvisionalModule)module).getURI();
580 if ((uri != null) && canLoad(uri)) {
581 it.remove();
582 Module m = loadAs(uri, module.getModuleId());
583 toBeDeployed.put(module.getModuleId(), m);
584 }
585 }
586 }
587 for (Map.Entry<ModuleId, Module> entry: toBeDeployed.entrySet()) {
588 deploy(entry.getKey(), entry.getValue());
589 }
590 }
591
592
593
594
595
596
597 protected class ModuleLoaders<E> extends LinkedHashSet<E> {
598
599
600
601
602
603
604
605 public boolean add(E o) {
606 boolean res = super.add(o);
607 if (deployedModules.getUnknownLoaderModulesCount() > 0) {
608 tryToDeployUnknown();
609 }
610 return res;
611 }
612
613 }
614
615
616 protected static String getUnsatisfiedDependenciesAsAList(Module module) {
617 StringBuffer res = new StringBuffer();
618 boolean first = true;
619
620
621 if (!module.getDependsOn().isEmpty()) {
622 for (Module m: module.getDependsOn()) {
623 int st = m.getState();
624 if ((st != Module.CREATED) && (st != Module.STARTED)) {
625 if (first) {
626 first = false;
627 res.append(m.getModuleId());
628 } else {
629 res.append(',').append(m.getModuleId());
630 }
631 }
632 }
633 }
634
635 return res.toString();
636 }
637
638
639
640
641
642 protected class DeployedModules<KeyType, ValueType> extends EnhancedMap<KeyType, ValueType> {
643
644
645 protected int unknownLoaderModules = 0;
646
647
648 public DeployedModules() {
649 }
650
651
652
653
654
655
656 public ValueType get(Object key) {
657 if (key instanceof String) {
658 String s = key.toString();
659 Iterator<Map.Entry<KeyType, ValueType>> it = entrySet().iterator();
660 while (it.hasNext()) {
661 Map.Entry<KeyType, ValueType> entry = it.next();
662 if ((entry.getKey() != null) && s.equals(entry.getKey().toString())) {
663 return entry.getValue();
664 }
665 }
666 return null;
667 } else {
668 return super.get(key);
669 }
670 }
671
672
673
674
675
676
677
678 public ValueType put(KeyType key, ValueType value) {
679 ValueType res = super.put(key, value);
680 if ((value instanceof ProvisionalModule) && !(res instanceof ProvisionalModule)) {
681 unknownLoaderModules = unknownLoaderModules + 1;
682 }
683 return res;
684 }
685
686
687
688
689
690
691 public ValueType remove(Object key) {
692 ValueType res = super.remove(key);
693 if (res instanceof ProvisionalModule) {
694 unknownLoaderModules = unknownLoaderModules - 1;
695 }
696 return res;
697 }
698
699
700
701
702 public void clear() {
703 super.clear();
704 unknownLoaderModules = 0;
705 }
706
707
708
709
710
711 public int getUnknownLoaderModulesCount() {
712 return unknownLoaderModules;
713 }
714 }
715 }