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    
020    import java.util.ArrayList;
021    import java.util.HashSet;
022    import java.util.List;
023    import java.util.Set;
024    import java.util.concurrent.CopyOnWriteArrayList;
025    
026    /**
027     * @author Ivica Cardic
028     * @author Brian Wing Shun Chan
029     */
030    public class HotDeployUtil {
031    
032            public static void fireDeployEvent(HotDeployEvent event) {
033                    _instance._fireDeployEvent(event);
034            }
035    
036            public static void fireUndeployEvent(HotDeployEvent event) {
037                    _instance._fireUndeployEvent(event);
038            }
039    
040            public static void flushPrematureEvents() {
041                    _instance._flushPrematureEvents();
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 unregisterListener(HotDeployListener listener) {
053                    _instance._unregisterListener(listener);
054            }
055    
056            public static void unregisterListeners() {
057                    _instance._unregisterListeners();
058            }
059    
060            private HotDeployUtil() {
061                    if (_log.isInfoEnabled()) {
062                            _log.info("Initializing hot deploy manager " + this.hashCode());
063                    }
064    
065                    _dependentEvents = new ArrayList<HotDeployEvent>();
066                    _deployedServletContextNames = new HashSet<String>();
067                    _listeners = new CopyOnWriteArrayList<HotDeployListener>();
068                    _prematureEvents = new ArrayList<HotDeployEvent>();
069            }
070    
071            private void _doFireDeployEvent(HotDeployEvent event) {
072                    if (_deployedServletContextNames.contains(
073                                    event.getServletContextName())) {
074    
075                            return;
076                    }
077    
078                    boolean hasDependencies = true;
079    
080                    Set<String> dependentServletContextNames =
081                            event.getDependentServletContextNames();
082    
083                    for (String dependentServletContextName :
084                                    dependentServletContextNames) {
085    
086                            if (!_deployedServletContextNames.contains(
087                                            dependentServletContextName)) {
088    
089                                    hasDependencies = false;
090    
091                                    break;
092                            }
093                    }
094    
095                    if (hasDependencies) {
096                            if (_dependentEvents.contains(event)) {
097                                    if (_log.isInfoEnabled()) {
098                                            _log.info(
099                                                    "Deploy " + event.getServletContextName() +
100                                                            " from queue");
101                                    }
102                            }
103    
104                            for (HotDeployListener listener : _listeners) {
105                                    try {
106                                            listener.invokeDeploy(event);
107                                    }
108                                    catch (HotDeployException hde) {
109                                            _log.error(hde, hde);
110                                    }
111                            }
112    
113                            _deployedServletContextNames.add(event.getServletContextName());
114    
115                            _dependentEvents.remove(event);
116    
117                            List<HotDeployEvent> dependentEvents =
118                                    new ArrayList<HotDeployEvent>(_dependentEvents);
119    
120                            for (HotDeployEvent dependentEvent : dependentEvents) {
121                                    _doFireDeployEvent(dependentEvent);
122                            }
123                    }
124                    else {
125                            if (!_dependentEvents.contains(event)) {
126                                    if (_log.isInfoEnabled()) {
127                                            _log.info(
128                                                    "Queue " + event.getServletContextName() +
129                                                            " for deploy because its dependencies are not " +
130                                                                    "available");
131                                    }
132    
133                                    _dependentEvents.add(event);
134                            }
135                    }
136            }
137    
138            private void _fireDeployEvent(HotDeployEvent event) {
139    
140                    // Capture events that are fired before the portal initialized. These
141                    // events are later fired by flushPrematureEvents.
142    
143                    if (_prematureEvents != null) {
144                            _prematureEvents.add(event);
145    
146                            return;
147                    }
148    
149                    // Fire current event
150    
151                    _doFireDeployEvent(event);
152            }
153    
154            private void _fireUndeployEvent(HotDeployEvent event) {
155                    for (HotDeployListener listener : _listeners) {
156                            try {
157                                    listener.invokeUndeploy(event);
158                            }
159                            catch (HotDeployException hde) {
160                                    _log.error(hde, hde);
161                            }
162                    }
163    
164                    _deployedServletContextNames.remove(event.getServletContextName());
165            }
166    
167            private void _flushPrematureEvents() {
168                    for (HotDeployEvent event : _prematureEvents) {
169                            _doFireDeployEvent(event);
170                    }
171    
172                    _prematureEvents = null;
173            }
174    
175            private void _registerListener(HotDeployListener listener) {
176                    _listeners.add(listener);
177            }
178    
179            private void _unregisterListener(HotDeployListener listener) {
180                    _listeners.remove(listener);
181            }
182    
183            private void _unregisterListeners() {
184                    _listeners.clear();
185            }
186    
187            private static Log _log = LogFactoryUtil.getLog(HotDeployUtil.class);
188    
189            private static HotDeployUtil _instance = new HotDeployUtil();
190    
191            private List<HotDeployEvent> _dependentEvents;
192            private Set<String> _deployedServletContextNames;
193            private List<HotDeployListener> _listeners;
194            private List<HotDeployEvent> _prematureEvents;
195    
196    }