1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.deploy;
20
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Queue;
29 import java.util.concurrent.ConcurrentLinkedQueue;
30
31 import org.eclipse.jetty.deploy.bindings.StandardDeployer;
32 import org.eclipse.jetty.deploy.bindings.StandardStarter;
33 import org.eclipse.jetty.deploy.bindings.StandardStopper;
34 import org.eclipse.jetty.deploy.bindings.StandardUndeployer;
35 import org.eclipse.jetty.deploy.graph.Edge;
36 import org.eclipse.jetty.deploy.graph.Node;
37 import org.eclipse.jetty.deploy.graph.Path;
38 import org.eclipse.jetty.server.Server;
39 import org.eclipse.jetty.server.handler.ContextHandlerCollection;
40 import org.eclipse.jetty.util.AttributesMap;
41 import org.eclipse.jetty.util.annotation.ManagedAttribute;
42 import org.eclipse.jetty.util.annotation.ManagedObject;
43 import org.eclipse.jetty.util.annotation.ManagedOperation;
44 import org.eclipse.jetty.util.annotation.Name;
45 import org.eclipse.jetty.util.component.ContainerLifeCycle;
46 import org.eclipse.jetty.util.log.Log;
47 import org.eclipse.jetty.util.log.Logger;
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 @ManagedObject("Deployment Manager")
64 public class DeploymentManager extends ContainerLifeCycle
65 {
66 private static final Logger LOG = Log.getLogger(DeploymentManager.class);
67
68
69
70
71 public class AppEntry
72 {
73
74
75
76
77
78 private int version;
79
80
81
82
83 private App app;
84
85
86
87
88 private Node lifecyleNode;
89
90
91
92
93 private Map<Node, Long> stateTimestamps = new HashMap<Node, Long>();
94
95 public App getApp()
96 {
97 return app;
98 }
99
100 public Node getLifecyleNode()
101 {
102 return lifecyleNode;
103 }
104
105 public Map<Node, Long> getStateTimestamps()
106 {
107 return stateTimestamps;
108 }
109
110 public int getVersion()
111 {
112 return version;
113 }
114
115 void setLifeCycleNode(Node node)
116 {
117 this.lifecyleNode = node;
118 this.stateTimestamps.put(node,Long.valueOf(System.currentTimeMillis()));
119 }
120 }
121
122 private final List<AppProvider> _providers = new ArrayList<AppProvider>();
123 private final AppLifeCycle _lifecycle = new AppLifeCycle();
124 private final Queue<AppEntry> _apps = new ConcurrentLinkedQueue<AppEntry>();
125 private AttributesMap _contextAttributes = new AttributesMap();
126 private ContextHandlerCollection _contexts;
127 private boolean _useStandardBindings = true;
128 private String _defaultLifeCycleGoal = AppLifeCycle.STARTED;
129
130
131
132
133
134
135
136 public void addApp(App app)
137 {
138 LOG.debug("Deployable added: {}",app.getOriginId());
139 AppEntry entry = new AppEntry();
140 entry.app = app;
141 entry.setLifeCycleNode(_lifecycle.getNodeByName("undeployed"));
142 _apps.add(entry);
143
144 if (isRunning() && _defaultLifeCycleGoal != null)
145 {
146
147 this.requestAppGoal(entry,_defaultLifeCycleGoal);
148 }
149 }
150
151
152
153
154
155
156
157 public void setAppProviders(Collection<AppProvider> providers)
158 {
159 if (isRunning())
160 throw new IllegalStateException();
161
162 _providers.clear();
163 removeBeans();
164 for (AppProvider provider:providers)
165 if (_providers.add(provider))
166 addBean(provider);
167 }
168
169 @ManagedAttribute("Application Providers")
170 public Collection<AppProvider> getAppProviders()
171 {
172 return Collections.unmodifiableList(_providers);
173 }
174
175 public void addAppProvider(AppProvider provider)
176 {
177 if (isRunning())
178 throw new IllegalStateException();
179 _providers.add(provider);
180 addBean(provider);
181 }
182
183 public void setLifeCycleBindings(Collection<AppLifeCycle.Binding> bindings)
184 {
185 if (isRunning())
186 throw new IllegalStateException();
187 for (AppLifeCycle.Binding b : _lifecycle.getBindings())
188 _lifecycle.removeBinding(b);
189 for (AppLifeCycle.Binding b : bindings)
190 _lifecycle.addBinding(b);
191 }
192
193 public Collection<AppLifeCycle.Binding> getLifeCycleBindings()
194 {
195 return Collections.unmodifiableSet(_lifecycle.getBindings());
196 }
197
198 public void addLifeCycleBinding(AppLifeCycle.Binding binding)
199 {
200 _lifecycle.addBinding(binding);
201 }
202
203
204
205
206
207
208
209
210 public void insertLifeCycleNode(String existingFromNodeName, String existingToNodeName, String insertedNodeName)
211 {
212 Node fromNode = _lifecycle.getNodeByName(existingFromNodeName);
213 Node toNode = _lifecycle.getNodeByName(existingToNodeName);
214 Edge edge = new Edge(fromNode,toNode);
215 _lifecycle.insertNode(edge,insertedNodeName);
216 }
217
218 @Override
219 protected void doStart() throws Exception
220 {
221 if (getContexts()==null)
222 throw new IllegalStateException("No Contexts");
223
224 if (_useStandardBindings)
225 {
226 LOG.debug("DeploymentManager using standard bindings");
227 addLifeCycleBinding(new StandardDeployer());
228 addLifeCycleBinding(new StandardStarter());
229 addLifeCycleBinding(new StandardStopper());
230 addLifeCycleBinding(new StandardUndeployer());
231 }
232
233
234 for (AppProvider provider : _providers)
235 {
236 startAppProvider(provider);
237 }
238 super.doStart();
239 }
240
241 @Override
242 protected void doStop() throws Exception
243 {
244
245 for (AppProvider provider : _providers)
246 {
247 try
248 {
249 provider.stop();
250 }
251 catch (Exception e)
252 {
253 LOG.warn("Unable to start AppProvider",e);
254 }
255 }
256 super.doStop();
257 }
258
259 private AppEntry findAppByOriginId(String originId)
260 {
261 if (originId == null)
262 {
263 return null;
264 }
265
266 for (AppEntry entry : _apps)
267 {
268 if (originId.equals(entry.app.getOriginId()))
269 {
270 return entry;
271 }
272 }
273 return null;
274 }
275
276 public App getAppByOriginId(String originId)
277 {
278 AppEntry entry = findAppByOriginId(originId);
279 if (entry == null)
280 {
281 return null;
282 }
283 return entry.app;
284 }
285
286 public Collection<AppEntry> getAppEntries()
287 {
288 return _apps;
289 }
290
291 @ManagedAttribute("Deployed Apps")
292 public Collection<App> getApps()
293 {
294 List<App> ret = new ArrayList<App>();
295 for (AppEntry entry : _apps)
296 {
297 ret.add(entry.app);
298 }
299 return ret;
300 }
301
302
303
304
305
306
307
308
309 public Collection<App> getApps(Node node)
310 {
311 List<App> ret = new ArrayList<App>();
312 for (AppEntry entry : _apps)
313 {
314 if (entry.lifecyleNode == node)
315 {
316 ret.add(entry.app);
317 }
318 }
319 return ret;
320 }
321
322 public List<App> getAppsWithSameContext(App app)
323 {
324 List<App> ret = new ArrayList<App>();
325 if (app == null)
326 {
327 return ret;
328 }
329
330 String contextId = app.getContextPath();
331 if (contextId == null)
332 {
333
334 return ret;
335 }
336
337 for (AppEntry entry : _apps)
338 {
339 if (entry.app.equals(app))
340 {
341
342
343 continue;
344 }
345
346 if (contextId.equals(entry.app.getContextPath()))
347 {
348 ret.add(entry.app);
349 }
350 }
351 return ret;
352 }
353
354
355
356
357
358
359
360 public Object getContextAttribute(String name)
361 {
362 return _contextAttributes.getAttribute(name);
363 }
364
365 public AttributesMap getContextAttributes()
366 {
367 return _contextAttributes;
368 }
369
370 @ManagedAttribute("Deployed Contexts")
371 public ContextHandlerCollection getContexts()
372 {
373 return _contexts;
374 }
375
376 public String getDefaultLifeCycleGoal()
377 {
378 return _defaultLifeCycleGoal;
379 }
380
381 public AppLifeCycle getLifeCycle()
382 {
383 return _lifecycle;
384 }
385
386 public Server getServer()
387 {
388 if (_contexts == null)
389 {
390 return null;
391 }
392 return _contexts.getServer();
393 }
394
395
396
397
398
399
400
401 public void removeApp(App app)
402 {
403 Iterator<AppEntry> it = _apps.iterator();
404 while (it.hasNext())
405 {
406 AppEntry entry = it.next();
407 if (entry.app.equals(app))
408 {
409 if (! AppLifeCycle.UNDEPLOYED.equals(entry.lifecyleNode.getName()))
410 requestAppGoal(entry.app,AppLifeCycle.UNDEPLOYED);
411 it.remove();
412 LOG.debug("Deployable removed: {}",entry.app);
413 }
414 }
415 }
416
417 public void removeAppProvider(AppProvider provider)
418 {
419 if(_providers.remove(provider))
420 removeBean(provider);
421
422 try
423 {
424 provider.stop();
425 }
426 catch (Exception e)
427 {
428 LOG.warn("Unable to stop Provider",e);
429 }
430 }
431
432
433
434
435
436
437 public void removeContextAttribute(String name)
438 {
439 _contextAttributes.removeAttribute(name);
440 }
441
442
443
444
445
446
447
448
449
450
451 public void requestAppGoal(App app, String nodeName)
452 {
453 AppEntry appentry = findAppByOriginId(app.getOriginId());
454 if (appentry == null)
455 {
456 throw new IllegalStateException("App not being tracked by Deployment Manager: " + app);
457 }
458
459 requestAppGoal(appentry,nodeName);
460 }
461
462
463
464
465
466
467
468
469
470
471 private void requestAppGoal(AppEntry appentry, String nodeName)
472 {
473 Node destinationNode = _lifecycle.getNodeByName(nodeName);
474 if (destinationNode == null)
475 {
476 throw new IllegalStateException("Node not present in Deployment Manager: " + nodeName);
477 }
478
479 Path path = _lifecycle.getPath(appentry.lifecyleNode,destinationNode);
480 if (path.isEmpty())
481 {
482
483 return;
484 }
485
486
487 try
488 {
489 Iterator<Node> it = path.getNodes().iterator();
490 if (it.hasNext())
491 {
492
493
494 it.next();
495 while (it.hasNext())
496 {
497 Node node = it.next();
498 LOG.debug("Executing Node {}",node);
499 _lifecycle.runBindings(node,appentry.app,this);
500 appentry.setLifeCycleNode(node);
501 }
502 }
503 }
504 catch (Throwable t)
505 {
506 LOG.warn("Unable to reach node goal: " + nodeName,t);
507 }
508 }
509
510
511
512
513
514
515
516
517
518
519 @ManagedOperation(value="request the app to be moved to the specified lifecycle node", impact="ACTION")
520 public void requestAppGoal(@Name("appId") String appId, @Name("nodeName") String nodeName)
521 {
522 AppEntry appentry = findAppByOriginId(appId);
523 if (appentry == null)
524 {
525 throw new IllegalStateException("App not being tracked by Deployment Manager: " + appId);
526 }
527 requestAppGoal(appentry,nodeName);
528 }
529
530
531
532
533
534
535
536 public void setContextAttribute(String name, Object value)
537 {
538 _contextAttributes.setAttribute(name,value);
539 }
540
541 public void setContextAttributes(AttributesMap contextAttributes)
542 {
543 this._contextAttributes = contextAttributes;
544 }
545
546 public void setContexts(ContextHandlerCollection contexts)
547 {
548 this._contexts = contexts;
549 }
550
551 public void setDefaultLifeCycleGoal(String defaultLifeCycleState)
552 {
553 this._defaultLifeCycleGoal = defaultLifeCycleState;
554 }
555
556 private void startAppProvider(AppProvider provider)
557 {
558 try
559 {
560 provider.setDeploymentManager(this);
561 provider.start();
562 }
563 catch (Exception e)
564 {
565 LOG.warn("Unable to start AppProvider",e);
566 }
567 }
568
569 public void undeployAll()
570 {
571 LOG.debug("Undeploy All");
572 for (AppEntry appentry : _apps)
573 {
574 requestAppGoal(appentry,"undeployed");
575 }
576 }
577
578 public boolean isUseStandardBindings()
579 {
580 return _useStandardBindings;
581 }
582
583 public void setUseStandardBindings(boolean useStandardBindings)
584 {
585 this._useStandardBindings = useStandardBindings;
586 }
587
588 public Collection<Node> getNodes()
589 {
590 return _lifecycle.getNodes();
591 }
592
593 @ManagedOperation(value="list apps that are located at specified App LifeCycle nodes", impact="ACTION")
594 public Collection<App> getApps(@Name("nodeName") String nodeName)
595 {
596 return getApps(_lifecycle.getNodeByName(nodeName));
597 }
598 }