001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portal.kernel.deploy.hot;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.util.BasePortalLifecycle;
020    import com.liferay.portal.kernel.util.PortalLifecycle;
021    import com.liferay.portal.kernel.util.PortalLifecycleUtil;
022    import com.liferay.portal.kernel.util.StringUtil;
023    
024    import java.util.ArrayList;
025    import java.util.Collections;
026    import java.util.HashSet;
027    import java.util.List;
028    import java.util.Set;
029    import java.util.concurrent.CopyOnWriteArrayList;
030    
031    /**
032     * @author Ivica Cardic
033     * @author Brian Wing Shun Chan
034     */
035    public class HotDeployUtil {
036    
037            public static void fireDeployEvent(HotDeployEvent event) {
038                    _instance._fireDeployEvent(event);
039            }
040    
041            public static void fireUndeployEvent(HotDeployEvent event) {
042                    _instance._fireUndeployEvent(event);
043            }
044    
045            public static void registerListener(HotDeployListener listener) {
046                    _instance._registerListener(listener);
047            }
048    
049            public static void reset() {
050                    _instance = new HotDeployUtil();
051            }
052    
053            public static void setCapturePrematureEvents(
054                    boolean capturePrematureEvents) {
055    
056                    _instance._setCapturePrematureEvents(capturePrematureEvents);
057            }
058    
059            public static void unregisterListener(HotDeployListener listener) {
060                    _instance._unregisterListener(listener);
061            }
062    
063            public static void unregisterListeners() {
064                    _instance._unregisterListeners();
065            }
066    
067            private HotDeployUtil() {
068                    if (_log.isInfoEnabled()) {
069                            _log.info("Initializing hot deploy manager " + this.hashCode());
070                    }
071    
072                    _dependentEvents = new ArrayList<HotDeployEvent>();
073                    _deployedServletContextNames = new HashSet<String>();
074                    _listeners = new CopyOnWriteArrayList<HotDeployListener>();
075            }
076    
077            private void _doFireDeployEvent(HotDeployEvent event) {
078                    if (_deployedServletContextNames.contains(
079                                    event.getServletContextName())) {
080    
081                            return;
082                    }
083    
084                    boolean hasDependencies = true;
085    
086                    for (String dependentServletContextName :
087                                    event.getDependentServletContextNames()) {
088    
089                            if (!_deployedServletContextNames.contains(
090                                            dependentServletContextName)) {
091    
092                                    hasDependencies = false;
093    
094                                    break;
095                            }
096                    }
097    
098                    if (hasDependencies) {
099                            if (_dependentEvents.contains(event)) {
100                                    if (_log.isInfoEnabled()) {
101                                            _log.info(
102                                                    "Deploying " + event.getServletContextName() +
103                                                            " from queue");
104                                    }
105                            }
106    
107                            for (HotDeployListener listener : _listeners) {
108                                    try {
109                                            listener.invokeDeploy(event);
110                                    }
111                                    catch (HotDeployException hde) {
112                                            _log.error(hde, hde);
113                                    }
114                            }
115    
116                            _deployedServletContextNames.add(event.getServletContextName());
117    
118                            _dependentEvents.remove(event);
119    
120                            List<HotDeployEvent> dependentEvents =
121                                    new ArrayList<HotDeployEvent>(_dependentEvents);
122    
123                            for (HotDeployEvent dependentEvent : dependentEvents) {
124                                    _doFireDeployEvent(dependentEvent);
125                            }
126                    }
127                    else {
128                            if (!_dependentEvents.contains(event)) {
129                                    if (_log.isInfoEnabled()) {
130                                            StringBuilder sb = new StringBuilder();
131    
132                                            sb.append("Queueing ");
133                                            sb.append(event.getServletContextName());
134                                            sb.append(" for deploy because it is missing ");
135                                            sb.append(_getRequiredServletContextNames(event));
136    
137                                            _log.info(sb.toString());
138                                    }
139    
140                                    _dependentEvents.add(event);
141                            }
142                            else {
143                                    if (_log.isInfoEnabled()) {
144                                            for (HotDeployEvent dependentEvent : _dependentEvents) {
145    
146                                                    StringBuilder sb = new StringBuilder();
147    
148                                                    sb.append(dependentEvent.getServletContextName());
149                                                    sb.append(" is still in queue because it is missing ");
150                                                    sb.append(
151                                                            _getRequiredServletContextNames(dependentEvent));
152    
153                                                    _log.info(sb.toString());
154                                            }
155                                    }
156                            }
157                    }
158            }
159    
160            private void _fireDeployEvent(final HotDeployEvent event) {
161                    if (_capturePrematureEvents) {
162    
163                            // Capture events that are fired before the portal initialized
164    
165                            PortalLifecycle portalLifecycle = new BasePortalLifecycle() {
166    
167                                    protected void doPortalDestroy() {
168                                    }
169    
170                                    protected void doPortalInit() {
171                                            HotDeployUtil.fireDeployEvent(event);
172                                    }
173    
174                            };
175    
176                            PortalLifecycleUtil.register(
177                                    portalLifecycle, PortalLifecycle.METHOD_INIT);
178                    }
179                    else {
180    
181                            // Fire current event
182    
183                            _doFireDeployEvent(event);
184                    }
185            }
186    
187            private void _fireUndeployEvent(HotDeployEvent event) {
188                    for (HotDeployListener listener : _listeners) {
189                            try {
190                                    listener.invokeUndeploy(event);
191                            }
192                            catch (HotDeployException hde) {
193                                    _log.error(hde, hde);
194                            }
195                    }
196    
197                    _deployedServletContextNames.remove(event.getServletContextName());
198            }
199    
200            private String _getRequiredServletContextNames(HotDeployEvent event) {
201                    List<String> requiredServletContextNames = new ArrayList<String>();
202    
203                    for (String dependentServletContextName :
204                                    event.getDependentServletContextNames()) {
205    
206                            if (!_deployedServletContextNames.contains(
207                                            dependentServletContextName)) {
208    
209                                    requiredServletContextNames.add(dependentServletContextName);
210                            }
211                    }
212    
213                    Collections.sort(requiredServletContextNames);
214    
215                    return StringUtil.merge(requiredServletContextNames, ", ");
216            }
217    
218            private void _registerListener(HotDeployListener listener) {
219                    _listeners.add(listener);
220            }
221    
222            private void _setCapturePrematureEvents(boolean capturePrematureEvents) {
223                    _capturePrematureEvents = capturePrematureEvents;
224            }
225    
226            private void _unregisterListener(HotDeployListener listener) {
227                    _listeners.remove(listener);
228            }
229    
230            private void _unregisterListeners() {
231                    _listeners.clear();
232            }
233    
234            private static Log _log = LogFactoryUtil.getLog(HotDeployUtil.class);
235    
236            private static HotDeployUtil _instance = new HotDeployUtil();
237    
238            private List<HotDeployEvent> _dependentEvents;
239            private Set<String> _deployedServletContextNames;
240            private List<HotDeployListener> _listeners;
241            private boolean _capturePrematureEvents = true;
242    
243    }