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