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 }