001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
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(portalLifecycle);
177                    }
178                    else {
179    
180                            // Fire current event
181    
182                            _doFireDeployEvent(event);
183                    }
184            }
185    
186            private void _fireUndeployEvent(HotDeployEvent event) {
187                    for (HotDeployListener listener : _listeners) {
188                            try {
189                                    listener.invokeUndeploy(event);
190                            }
191                            catch (HotDeployException hde) {
192                                    _log.error(hde, hde);
193                            }
194                    }
195    
196                    _deployedServletContextNames.remove(event.getServletContextName());
197            }
198    
199            private String _getRequiredServletContextNames(HotDeployEvent event) {
200                    List<String> requiredServletContextNames = new ArrayList<String>();
201    
202                    for (String dependentServletContextName :
203                                    event.getDependentServletContextNames()) {
204    
205                            if (!_deployedServletContextNames.contains(
206                                            dependentServletContextName)) {
207    
208                                    requiredServletContextNames.add(dependentServletContextName);
209                            }
210                    }
211    
212                    Collections.sort(requiredServletContextNames);
213    
214                    return StringUtil.merge(requiredServletContextNames, ", ");
215            }
216    
217            private void _registerListener(HotDeployListener listener) {
218                    _listeners.add(listener);
219            }
220    
221            private void _setCapturePrematureEvents(boolean capturePrematureEvents) {
222                    _capturePrematureEvents = capturePrematureEvents;
223            }
224    
225            private void _unregisterListener(HotDeployListener listener) {
226                    _listeners.remove(listener);
227            }
228    
229            private void _unregisterListeners() {
230                    _listeners.clear();
231            }
232    
233            private static Log _log = LogFactoryUtil.getLog(HotDeployUtil.class);
234    
235            private static HotDeployUtil _instance = new HotDeployUtil();
236    
237            private List<HotDeployEvent> _dependentEvents;
238            private Set<String> _deployedServletContextNames;
239            private List<HotDeployListener> _listeners;
240            private boolean _capturePrematureEvents = true;
241    
242    }