KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > server > deploy > DeployController


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.server.deploy;
31
32 import com.caucho.config.ConfigException;
33 import com.caucho.config.types.Period;
34 import com.caucho.lifecycle.Lifecycle;
35 import com.caucho.lifecycle.LifecycleListener;
36 import com.caucho.loader.DynamicClassLoader;
37 import com.caucho.util.Alarm;
38 import com.caucho.util.AlarmListener;
39 import com.caucho.util.L10N;
40 import com.caucho.util.WeakAlarm;
41 import com.caucho.vfs.Dependency;
42
43 import java.io.IOException JavaDoc;
44 import java.util.logging.Level JavaDoc;
45 import java.util.logging.Logger JavaDoc;
46
47 /**
48  * DeployController controls the lifecycle of the DeployInstance.
49  */

50 abstract public class DeployController<I extends DeployInstance>
51   implements Dependency, AlarmListener
52 {
53   private static final Logger JavaDoc log
54     = Logger.getLogger(DeployController.class.getName());
55   private static final L10N L = new L10N(DeployController.class);
56
57   public static final String JavaDoc STARTUP_DEFAULT = "default";
58   public static final String JavaDoc STARTUP_AUTOMATIC = "automatic";
59   public static final String JavaDoc STARTUP_LAZY = "lazy";
60   public static final String JavaDoc STARTUP_MANUAL = "manual";
61
62   public static final String JavaDoc REDEPLOY_DEFAULT = "default";
63   public static final String JavaDoc REDEPLOY_AUTOMATIC = "automatic";
64   public static final String JavaDoc REDEPLOY_LAZY = "lazy";
65   public static final String JavaDoc REDEPLOY_MANUAL = "manual";
66   
67   public static final long REDEPLOY_CHECK_INTERVAL = 60000;
68
69   private ClassLoader JavaDoc _parentLoader;
70   
71   private String JavaDoc _id;
72
73   private String JavaDoc _startupMode = STARTUP_DEFAULT;
74   private String JavaDoc _redeployMode = REDEPLOY_DEFAULT;
75
76   private DeployControllerStrategy _strategy;
77
78   protected final Lifecycle _lifecycle;
79
80   private Alarm _alarm = new WeakAlarm(this);
81   private long _redeployCheckInterval = REDEPLOY_CHECK_INTERVAL;
82
83   private long _startTime;
84   private I _deployInstance;
85
86   protected DeployController(String JavaDoc id)
87   {
88     this(id, null);
89   }
90
91   protected DeployController(String JavaDoc id, ClassLoader JavaDoc parentLoader)
92   {
93     _id = id;
94     
95     if (parentLoader == null)
96       parentLoader = Thread.currentThread().getContextClassLoader();
97     
98     _parentLoader = parentLoader;
99
100     _lifecycle = new Lifecycle(getLog(), toString());
101   }
102
103   public void addLifecycleListener(LifecycleListener listener)
104   {
105     _lifecycle.addListener(listener);
106   }
107
108   /**
109    * Returns the controller's id.
110    */

111   public final String JavaDoc getId()
112   {
113     return _id;
114   }
115
116   /**
117    * Returns the parent class loader.
118    */

119   public ClassLoader JavaDoc getParentClassLoader()
120   {
121     return _parentLoader;
122   }
123
124   /**
125    * Sets the startup mode.
126    */

127   public void setStartupMode(String JavaDoc mode)
128   {
129     try {
130       _startupMode = toStartupCode(mode);
131     } catch (Exception JavaDoc e) {
132       throw new RuntimeException JavaDoc(e);
133     }
134   }
135
136   /**
137    * Merges with the old controller.
138    */

139   protected void mergeController(DeployController newController)
140   {
141     newController._parentLoader = _parentLoader;
142   }
143
144   /**
145    * Merge the startup mode.
146    */

147   public void mergeStartupMode(String JavaDoc mode)
148   {
149     if (mode == null || STARTUP_DEFAULT.equals(mode))
150       return;
151
152     _startupMode = mode;
153   }
154
155   /**
156    * Returns the startup mode.
157    */

158   public String JavaDoc getStartupMode()
159   {
160     return _startupMode;
161   }
162
163   /**
164    * Converts startup mode to code.
165    */

166   public static String JavaDoc toStartupCode(String JavaDoc mode)
167     throws ConfigException
168   {
169     if ("automatic".equals(mode))
170       return STARTUP_AUTOMATIC;
171     else if ("lazy".equals(mode))
172       return STARTUP_LAZY;
173     else if ("manual".equals(mode))
174       return STARTUP_MANUAL;
175     else {
176       throw new ConfigException(L.l("'{0}' is an unknown startup-mode. 'automatic', 'lazy', and 'manual' are the acceptable values.",
177                     mode));
178     }
179   }
180
181   /**
182    * Sets the redeploy mode.
183    */

184   public void setRedeployMode(String JavaDoc mode)
185   {
186     try {
187       _redeployMode = toRedeployCode(mode);
188     } catch (Exception JavaDoc e) {
189       throw new RuntimeException JavaDoc(e);
190     }
191   }
192
193   /**
194    * Merge the redeploy mode.
195    */

196   public void mergeRedeployMode(String JavaDoc mode)
197   {
198     if (mode == null || REDEPLOY_DEFAULT.equals(mode))
199       return;
200
201     _redeployMode = mode;
202   }
203
204   /**
205    * Returns the redeploy mode.
206    */

207   public String JavaDoc getRedeployMode()
208   {
209     return _redeployMode;
210   }
211
212   /**
213    * Converts redeploy mode to code.
214    */

215   public static String JavaDoc toRedeployCode(String JavaDoc mode)
216     throws ConfigException
217   {
218     if ("automatic".equals(mode))
219       return REDEPLOY_AUTOMATIC;
220     else if ("lazy".equals(mode))
221       return REDEPLOY_LAZY;
222     else if ("manual".equals(mode))
223       return REDEPLOY_MANUAL;
224     else
225       throw new ConfigException(L.l("'{0}' is an unknown redeploy-mode. 'automatic', 'lazy', and 'manual' are the acceptable values.",
226                     mode));
227   }
228
229   /**
230    * Sets the redeploy-check-interval
231    */

232   public void mergeRedeployCheckInterval(long interval)
233   {
234     if (interval != REDEPLOY_CHECK_INTERVAL)
235       _redeployCheckInterval = interval;
236   }
237
238   /**
239    * Sets the redeploy-check-interval
240    */

241   public void setRedeployCheckInterval(Period period)
242   {
243     _redeployCheckInterval = period.getPeriod();
244
245     if (_redeployCheckInterval < 0)
246       _redeployCheckInterval = Period.INFINITE;
247
248     if (_redeployCheckInterval < 5000)
249       _redeployCheckInterval = 5000;
250   }
251
252   /**
253    * Gets the redeploy-check-interval
254    */

255   public long getRedeployCheckInterval()
256   {
257     return _redeployCheckInterval;
258   }
259
260   /**
261    * Returns true if the entry matches.
262    */

263   public boolean isNameMatch(String JavaDoc name)
264   {
265     return getId().equals(name);
266   }
267
268   /**
269    * Returns the start time of the entry.
270    */

271   public long getStartTime()
272   {
273     return _startTime;
274   }
275
276   /**
277    * Returns the deploy admin.
278    */

279   protected DeployControllerAdmin getDeployAdmin()
280   {
281     return null;
282   }
283   
284   /**
285    * Initialize the entry.
286    */

287   public final boolean init()
288   {
289     if (! _lifecycle.toInitializing())
290       return false;
291
292     Thread JavaDoc thread = Thread.currentThread();
293     ClassLoader JavaDoc oldLoader = thread.getContextClassLoader();
294
295     try {
296       thread.setContextClassLoader(getParentClassLoader());
297
298       initBegin();
299
300       if (_startupMode == STARTUP_MANUAL) {
301     if (_redeployMode == REDEPLOY_AUTOMATIC) {
302       throw new IllegalStateException JavaDoc(L.l("startup='manual' and redeploy='automatic' is an unsupported combination."));
303     }
304     else
305       _strategy = StartManualRedeployManualStrategy.create();
306       }
307       else if (_startupMode == STARTUP_LAZY) {
308     if (_redeployMode == REDEPLOY_MANUAL)
309       _strategy = StartLazyRedeployManualStrategy.create();
310     else
311       _strategy = StartLazyRedeployAutomaticStrategy.create();
312       }
313       else {
314     if (_redeployMode == STARTUP_MANUAL)
315       _strategy = StartAutoRedeployManualStrategy.create();
316     else
317       _strategy = StartAutoRedeployAutoStrategy.create();
318       }
319
320       initEnd();
321
322       return _lifecycle.toInit();
323     } finally {
324       thread.setContextClassLoader(oldLoader);
325     }
326   }
327
328   /**
329    * Initial calls for init.
330    */

331   protected void initBegin()
332   {
333   }
334
335   /**
336    * Final calls for init.
337    */

338   protected void initEnd()
339   {
340   }
341
342   protected String JavaDoc getMBeanTypeName()
343   {
344     String JavaDoc className = getDeployInstance().getClass().getName();
345     int p = className.lastIndexOf('.');
346     if (p > 0)
347       className = className.substring(p + 1);
348
349     return className;
350   }
351
352   protected String JavaDoc getMBeanId()
353   {
354     String JavaDoc name = getId();
355     if (name == null || name.equals(""))
356       name = "default";
357
358     return name;
359   }
360
361   /**
362    * Returns the state name.
363    */

364   public String JavaDoc getState()
365   {
366     if (isDestroyed())
367       return "destroyed";
368     else if (isStoppedLazy())
369       return "stopped-lazy";
370     else if (isStopped())
371       return "stopped";
372     else if (isError())
373       return "error";
374     else if (isModified())
375       return "active-modified";
376     else
377       return "active";
378   }
379
380   /**
381    * Returns true if the instance is in the active state.
382    */

383   public boolean isActive()
384   {
385     return _lifecycle.isActive();
386   }
387
388   /**
389    * Returns true if the instance is in the stopped state.
390    *
391    * @return true on stopped state
392    */

393   public boolean isStopped()
394   {
395     return _lifecycle.isStopped() || _lifecycle.isInit();
396   }
397
398   /**
399    * Returns true for the stop-lazy state
400    */

401   public boolean isStoppedLazy()
402   {
403     return _lifecycle.isInit();
404   }
405
406   /**
407    * Returns true if the instance has been idle for longer than its timeout.
408    *
409    * @return true if idle
410    */

411   public boolean isActiveIdle()
412   {
413     DeployInstance instance = getDeployInstance();
414
415     if (! _lifecycle.isActive())
416       return false;
417     else if (instance == null)
418       return false;
419     else
420       return instance.isDeployIdle();
421   }
422
423   /**
424    * Return true if the instance is in the error state.
425    *
426    * @return true for the error state.
427    */

428   public boolean isError()
429   {
430     if (_lifecycle.isError())
431       return true;
432
433     DeployInstance instance = getDeployInstance();
434
435     return (instance != null &&
436             instance.getConfigException() != null);
437   }
438
439   /**
440    * Returns true if there's currently an error.
441    */

442   public boolean isErrorNow()
443   {
444     if (_lifecycle.isError())
445       return true;
446     
447     DeployInstance instance = getDeployInstance();
448
449     return (instance != null &&
450             instance.getConfigException() != null);
451   }
452
453   /**
454    * Returns true if the entry is modified.
455    */

456   public boolean isModified()
457   {
458     DeployInstance instance = getDeployInstance();
459
460     return instance == null || instance.isModified();
461   }
462
463   /**
464    * Returns true if the entry is modified.
465    */

466   public boolean isModifiedNow()
467   {
468     DeployInstance instance = getDeployInstance();
469
470     return instance == null || instance.isModifiedNow();
471   }
472
473   /**
474    * Returns the current instance.
475    */

476   public final I getDeployInstance()
477   {
478     synchronized (this) {
479       if (_deployInstance == null) {
480     Thread JavaDoc thread = Thread.currentThread();
481     ClassLoader JavaDoc oldLoader = thread.getContextClassLoader();
482
483     try {
484       thread.setContextClassLoader(_parentLoader);
485       
486       _deployInstance = instantiateDeployInstance();
487     } finally {
488       thread.setContextClassLoader(oldLoader);
489     }
490       }
491
492       return _deployInstance;
493     }
494   }
495
496   /**
497    * Redeploys the entry if it's modified.
498    */

499   public void startOnInit()
500   {
501     if (! _lifecycle.isAfterInit())
502       throw new IllegalStateException JavaDoc(L.l("startOnInit must be called after init (in '{0}')",
503                                           _lifecycle.getStateName()));
504
505     _strategy.startOnInit(this);
506   }
507
508   /**
509    * Force an instance start from an admin command.
510    */

511   public final void start()
512   {
513     _strategy.start(this);
514   }
515
516
517   public Throwable JavaDoc getConfigException()
518   {
519     return null;
520   }
521
522   /**
523    * Stops the controller from an admin command.
524    */

525   public final void stop()
526   {
527     _strategy.stop(this);
528   }
529
530   /**
531    * Force an instance restart from an admin command.
532    */

533   public final void restart()
534   {
535     _strategy.stop(this);
536     _strategy.start(this);
537   }
538
539   /**
540    * Update the controller from an admin command.
541    */

542   public final void update()
543   {
544     _strategy.update(this);
545   }
546
547   /**
548    * Returns the instance for a top-level request
549    * @return the request object or null for none.
550    */

551   public I request()
552   {
553     if (_lifecycle.isDestroyed())
554       return null;
555     else if (_strategy != null)
556       return _strategy.request(this);
557     else
558       return null;
559   }
560
561   /**
562    * Returns the instance for a subrequest.
563    *
564    * @return the request object or null for none.
565    */

566   public I subrequest()
567   {
568     if (_lifecycle.isDestroyed())
569       return null;
570     else if (_strategy != null)
571       return _strategy.subrequest(this);
572     else
573       return null;
574   }
575
576   /**
577    * Restarts the instance
578    *
579    * @return the new instance
580    */

581   I restartImpl()
582   {
583     if (! _lifecycle.isStopped() && ! _lifecycle.isInit())
584       stopImpl();
585
586     return startImpl();
587   }
588
589   /**
590    * Starts the entry.
591    */

592   protected I startImpl()
593   {
594     assert(_lifecycle.isAfterInit());
595
596     if (DynamicClassLoader.isModified(_parentLoader)) {
597       _deployInstance = null;
598       return null;
599     }
600
601     I deployInstance = getDeployInstance();
602
603     Thread JavaDoc thread = Thread.currentThread();
604     ClassLoader JavaDoc oldLoader = thread.getContextClassLoader();
605     ClassLoader JavaDoc loader = null;
606     boolean isStarting = false;
607
608     try {
609       loader = deployInstance.getClassLoader();
610       thread.setContextClassLoader(loader);
611
612       isStarting = _lifecycle.toStarting();
613       
614       if (! isStarting)
615     return deployInstance;
616       
617       expandArchive();
618     
619       addManifestClassPath();
620       
621       configureInstance(deployInstance);
622
623       deployInstance.start();
624
625       _startTime = Alarm.getCurrentTime();
626     } catch (ConfigException e) {
627       log.severe(e.toString());
628       log.log(Level.FINE, e.toString(), e);
629
630       _lifecycle.toError();
631
632       if (deployInstance != null)
633     deployInstance.setConfigException(e);
634     } catch (Throwable JavaDoc e) {
635       log.log(Level.SEVERE, e.toString(), e);
636
637       _lifecycle.toError();
638
639       if (deployInstance != null)
640     deployInstance.setConfigException(e);
641     } finally {
642       if (isStarting)
643     _lifecycle.toActive();
644
645       // server/
646
if (loader instanceof DynamicClassLoader)
647     ((DynamicClassLoader) loader).clearModified();
648
649       if (_alarm != null)
650     _alarm.queue(_redeployCheckInterval); // XXX: strategy-controlled
651

652       thread.setContextClassLoader(oldLoader);
653     }
654
655     return deployInstance;
656   }
657
658   /**
659    * Deploys the entry, e.g. archive expansion.
660    */

661   protected void expandArchive()
662     throws Exception JavaDoc
663   {
664   }
665
666   /**
667    * Stops the current instance, putting it in the lazy state.
668    */

669   void stopLazyImpl()
670   {
671     if (_lifecycle.isInit())
672       return;
673
674     stopImpl();
675
676     _lifecycle.toPostInit();
677   }
678
679   /**
680    * Stops the current instance.
681    */

682   void stopImpl()
683   {
684     Thread JavaDoc thread = Thread.currentThread();
685     ClassLoader JavaDoc oldLoader = thread.getContextClassLoader();
686     
687     DeployInstance oldInstance = _deployInstance;
688     boolean isStopping = false;
689
690     if (oldInstance != null)
691       thread.setContextClassLoader(oldInstance.getClassLoader());
692
693     try {
694       isStopping = _lifecycle.toStopping();
695
696       if (! isStopping)
697     return;
698
699       synchronized (this) {
700         oldInstance = _deployInstance;
701         _deployInstance = null;
702       }
703
704       if (oldInstance != null) {
705     oldInstance.destroy();
706       }
707     } finally {
708       if (isStopping)
709     _lifecycle.toStop();
710       
711       thread.setContextClassLoader(oldLoader);
712     }
713
714     return;
715   }
716
717   /**
718    * Creates an instance.
719    */

720   abstract protected I instantiateDeployInstance();
721
722   /**
723    * Adds any manifest Class-Path
724    */

725   protected void addManifestClassPath()
726     throws IOException JavaDoc
727   {
728   }
729
730   /**
731    * Configuration of the instance
732    */

733   protected void configureInstance(I deployInstance)
734     throws Throwable JavaDoc
735   {
736   }
737
738   /**
739    * Handles the redeploy check alarm.
740    */

741   public void handleAlarm(Alarm alarm)
742   {
743     try {
744       _strategy.alarm(this);
745     } finally {
746       if (! _lifecycle.isDestroyed())
747     alarm.queue(_redeployCheckInterval);
748     }
749   }
750
751   /**
752    * Returns true if the entry is destroyed.
753    */

754   public boolean isDestroyed()
755   {
756     return _lifecycle.isDestroyed();
757   }
758
759   /**
760    * Destroys the entry.
761    */

762   protected boolean destroy()
763   {
764     if (_lifecycle.isAfterInit())
765       stop();
766
767     if (! _lifecycle.toDestroy())
768       return false;
769
770     Alarm alarm = _alarm;
771     _alarm = null;
772
773     if (alarm != null) {
774       alarm.dequeue();
775     }
776     
777     return true;
778   }
779
780   /**
781    * Returns the appropriate log for debugging.
782    */

783   protected Logger JavaDoc getLog()
784   {
785     return log;
786   }
787
788   /**
789    * Returns the entry's debug name.
790    */

791   public String JavaDoc toString()
792   {
793     String JavaDoc className = getClass().getName();
794     int p = className.lastIndexOf('.');
795
796     return className.substring(p + 1) + "[" + getId() + "]";
797   }
798 }
799
Popular Tags