1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   *
12   *
13   */
14  
15  package com.liferay.portal.kernel.deploy.hot;
16  
17  import com.liferay.portal.kernel.log.Log;
18  import com.liferay.portal.kernel.log.LogFactoryUtil;
19  import com.liferay.portal.kernel.util.BasePortalLifecycle;
20  import com.liferay.portal.kernel.util.PortalLifecycle;
21  import com.liferay.portal.kernel.util.PortalLifecycleUtil;
22  import com.liferay.portal.kernel.util.StringUtil;
23  
24  import java.util.ArrayList;
25  import java.util.Collections;
26  import java.util.HashSet;
27  import java.util.List;
28  import java.util.Set;
29  import java.util.concurrent.CopyOnWriteArrayList;
30  
31  /**
32   * <a href="HotDeployUtil.java.html"><b><i>View Source</i></b></a>
33   *
34   * @author Ivica Cardic
35   * @author Brian Wing Shun Chan
36   */
37  public class HotDeployUtil {
38  
39      public static void fireDeployEvent(HotDeployEvent event) {
40          _instance._fireDeployEvent(event);
41      }
42  
43      public static void fireUndeployEvent(HotDeployEvent event) {
44          _instance._fireUndeployEvent(event);
45      }
46  
47      public static void registerListener(HotDeployListener listener) {
48          _instance._registerListener(listener);
49      }
50  
51      public static void reset() {
52          _instance._reset();
53      }
54  
55      public static void setCapturePrematureEvents(
56          boolean capturePrematureEvents) {
57  
58          _instance._setCapturePrematureEvents(capturePrematureEvents);
59      }
60  
61      public static void unregisterListener(HotDeployListener listener) {
62          _instance._unregisterListener(listener);
63      }
64  
65      public static void unregisterListeners() {
66          _instance._unregisterListeners();
67      }
68  
69      private HotDeployUtil() {
70          if (_log.isInfoEnabled()) {
71              _log.info("Initializing hot deploy manager " + this.hashCode());
72          }
73  
74          _dependentEvents = new ArrayList<HotDeployEvent>();
75          _deployedServletContextNames = new HashSet<String>();
76          _listeners = new CopyOnWriteArrayList<HotDeployListener>();
77      }
78  
79      private void _doFireDeployEvent(HotDeployEvent event) {
80          if (_deployedServletContextNames.contains(
81                  event.getServletContextName())) {
82  
83              return;
84          }
85  
86          boolean hasDependencies = true;
87  
88          for (String dependentServletContextName :
89                  event.getDependentServletContextNames()) {
90  
91              if (!_deployedServletContextNames.contains(
92                      dependentServletContextName)) {
93  
94                  hasDependencies = false;
95  
96                  break;
97              }
98          }
99  
100         if (hasDependencies) {
101             if (_dependentEvents.contains(event)) {
102                 if (_log.isInfoEnabled()) {
103                     _log.info(
104                         "Deploying " + event.getServletContextName() +
105                             " from queue");
106                 }
107             }
108 
109             for (HotDeployListener listener : _listeners) {
110                 try {
111                     listener.invokeDeploy(event);
112                 }
113                 catch (HotDeployException hde) {
114                     _log.error(hde, hde);
115                 }
116             }
117 
118             _deployedServletContextNames.add(event.getServletContextName());
119 
120             _dependentEvents.remove(event);
121 
122             List<HotDeployEvent> dependentEvents =
123                 new ArrayList<HotDeployEvent>(_dependentEvents);
124 
125             for (HotDeployEvent dependentEvent : dependentEvents) {
126                 _doFireDeployEvent(dependentEvent);
127             }
128         }
129         else {
130             if (!_dependentEvents.contains(event)) {
131                 if (_log.isInfoEnabled()) {
132                     StringBuilder sb = new StringBuilder();
133 
134                     sb.append("Queueing ");
135                     sb.append(event.getServletContextName());
136                     sb.append(" for deploy because it is missing ");
137                     sb.append(_getRequiredServletContextNames(event));
138 
139                     _log.info(sb.toString());
140                 }
141 
142                 _dependentEvents.add(event);
143             }
144             else {
145                 if (_log.isInfoEnabled()) {
146                     for (HotDeployEvent dependentEvent : _dependentEvents) {
147 
148                         StringBuilder sb = new StringBuilder();
149 
150                         sb.append(dependentEvent.getServletContextName());
151                         sb.append(" is still in queue because it is missing ");
152                         sb.append(
153                             _getRequiredServletContextNames(dependentEvent));
154 
155                         _log.info(sb.toString());
156                     }
157                 }
158             }
159         }
160     }
161 
162     private void _fireDeployEvent(final HotDeployEvent event) {
163         if (_capturePrematureEvents) {
164 
165             // Capture events that are fired before the portal initialized
166 
167             PortalLifecycle portalLifecycle = new BasePortalLifecycle() {
168 
169                 protected void doPortalDestroy() {
170                 }
171 
172                 protected void doPortalInit() {
173                     HotDeployUtil.fireDeployEvent(event);
174                 }
175 
176             };
177 
178             PortalLifecycleUtil.register(
179                 portalLifecycle, PortalLifecycle.METHOD_INIT);
180         }
181         else {
182 
183             // Fire current event
184 
185             _doFireDeployEvent(event);
186         }
187     }
188 
189     private void _fireUndeployEvent(HotDeployEvent event) {
190         for (HotDeployListener listener : _listeners) {
191             try {
192                 listener.invokeUndeploy(event);
193             }
194             catch (HotDeployException hde) {
195                 _log.error(hde, hde);
196             }
197         }
198 
199         _deployedServletContextNames.remove(event.getServletContextName());
200     }
201 
202     private String _getRequiredServletContextNames(HotDeployEvent event) {
203         List<String> requiredServletContextNames = new ArrayList<String>();
204 
205         for (String dependentServletContextName :
206                 event.getDependentServletContextNames()) {
207 
208             if (!_deployedServletContextNames.contains(
209                     dependentServletContextName)) {
210 
211                 requiredServletContextNames.add(dependentServletContextName);
212             }
213         }
214 
215         Collections.sort(requiredServletContextNames);
216 
217         return StringUtil.merge(requiredServletContextNames, ", ");
218     }
219 
220     private void _registerListener(HotDeployListener listener) {
221         _listeners.add(listener);
222     }
223 
224     private void _reset() {
225         _capturePrematureEvents = true;
226         _dependentEvents.clear();
227         _deployedServletContextNames.clear();
228         _listeners.clear();
229     }
230 
231     private void _setCapturePrematureEvents(boolean capturePrematureEvents) {
232         _capturePrematureEvents = capturePrematureEvents;
233     }
234 
235     private void _unregisterListener(HotDeployListener listener) {
236         _listeners.remove(listener);
237     }
238 
239     private void _unregisterListeners() {
240         _listeners.clear();
241     }
242 
243     private static Log _log = LogFactoryUtil.getLog(HotDeployUtil.class);
244 
245     private static HotDeployUtil _instance = new HotDeployUtil();
246 
247     private boolean _capturePrematureEvents = true;
248     private List<HotDeployEvent> _dependentEvents;
249     private Set<String> _deployedServletContextNames;
250     private List<HotDeployListener> _listeners;
251 
252 }