001
014
015 package com.liferay.portal.deploy.hot;
016
017 import com.liferay.portal.kernel.deploy.hot.HotDeploy;
018 import com.liferay.portal.kernel.deploy.hot.HotDeployEvent;
019 import com.liferay.portal.kernel.deploy.hot.HotDeployException;
020 import com.liferay.portal.kernel.deploy.hot.HotDeployListener;
021 import com.liferay.portal.kernel.log.Log;
022 import com.liferay.portal.kernel.log.LogFactoryUtil;
023 import com.liferay.portal.kernel.portlet.PortletClassLoaderUtil;
024 import com.liferay.portal.kernel.security.pacl.DoPrivileged;
025 import com.liferay.portal.kernel.servlet.ServletContextPool;
026 import com.liferay.portal.kernel.template.TemplateManagerUtil;
027 import com.liferay.portal.kernel.util.BasePortalLifecycle;
028 import com.liferay.portal.kernel.util.HttpUtil;
029 import com.liferay.portal.kernel.util.PortalLifecycle;
030 import com.liferay.portal.kernel.util.PortalLifecycleUtil;
031 import com.liferay.portal.kernel.util.PropertiesUtil;
032 import com.liferay.portal.kernel.util.StringBundler;
033 import com.liferay.portal.kernel.util.StringUtil;
034 import com.liferay.portal.util.ClassLoaderUtil;
035
036 import java.util.ArrayList;
037 import java.util.Collections;
038 import java.util.HashSet;
039 import java.util.List;
040 import java.util.Properties;
041 import java.util.Set;
042 import java.util.concurrent.CopyOnWriteArrayList;
043
044 import javax.servlet.ServletContext;
045
046
051 @DoPrivileged
052 public class HotDeployImpl implements HotDeploy {
053
054 public HotDeployImpl() {
055 if (_log.isDebugEnabled()) {
056 _log.debug("Initializing hot deploy manager " + this.hashCode());
057 }
058
059 _dependentHotDeployEvents = new ArrayList<HotDeployEvent>();
060 _deployedServletContextNames = new HashSet<String>();
061 _hotDeployListeners = new CopyOnWriteArrayList<HotDeployListener>();
062 }
063
064 public synchronized void fireDeployEvent(
065 final HotDeployEvent hotDeployEvent) {
066
067 PortalLifecycleUtil.register(
068 new HotDeployPortalLifecycle(hotDeployEvent),
069 PortalLifecycle.METHOD_INIT);
070
071 if (_capturePrematureEvents) {
072
073
074
075 PortalLifecycle portalLifecycle = new BasePortalLifecycle() {
076
077 @Override
078 protected void doPortalDestroy() {
079 }
080
081 @Override
082 protected void doPortalInit() {
083 fireDeployEvent(hotDeployEvent);
084 }
085
086 };
087
088 PortalLifecycleUtil.register(
089 portalLifecycle, PortalLifecycle.METHOD_INIT);
090 }
091 else {
092
093
094
095 doFireDeployEvent(hotDeployEvent);
096 }
097 }
098
099 public synchronized void fireUndeployEvent(HotDeployEvent hotDeployEvent) {
100 for (HotDeployListener hotDeployListener : _hotDeployListeners) {
101 try {
102 PortletClassLoaderUtil.setClassLoader(
103 hotDeployEvent.getContextClassLoader());
104 PortletClassLoaderUtil.setServletContextName(
105 hotDeployEvent.getServletContextName());
106
107 hotDeployListener.invokeUndeploy(hotDeployEvent);
108 }
109 catch (HotDeployException hde) {
110 _log.error(hde, hde);
111 }
112 finally {
113 PortletClassLoaderUtil.setClassLoader(null);
114 PortletClassLoaderUtil.setServletContextName(null);
115 }
116 }
117
118 _deployedServletContextNames.remove(
119 hotDeployEvent.getServletContextName());
120
121 ClassLoader classLoader = hotDeployEvent.getContextClassLoader();
122
123 TemplateManagerUtil.destroy(classLoader);
124
125 _pacl.unregister(classLoader);
126 }
127
128 public void registerListener(HotDeployListener hotDeployListener) {
129 _hotDeployListeners.add(hotDeployListener);
130 }
131
132 public synchronized void reset() {
133 _capturePrematureEvents = true;
134 _dependentHotDeployEvents.clear();
135 _deployedServletContextNames.clear();
136 _hotDeployListeners.clear();
137 }
138
139 public synchronized void setCapturePrematureEvents(
140 boolean capturePrematureEvents) {
141
142 _capturePrematureEvents = capturePrematureEvents;
143 }
144
145 public void unregisterListener(HotDeployListener hotDeployListener) {
146 _hotDeployListeners.remove(hotDeployListener);
147 }
148
149 public void unregisterListeners() {
150 _hotDeployListeners.clear();
151 }
152
153 protected void doFireDeployEvent(HotDeployEvent hotDeployEvent) {
154 String servletContextName = hotDeployEvent.getServletContextName();
155
156 if (_deployedServletContextNames.contains(servletContextName)) {
157 return;
158 }
159
160 boolean hasDependencies = true;
161
162 for (String dependentServletContextName :
163 hotDeployEvent.getDependentServletContextNames()) {
164
165 if (!_deployedServletContextNames.contains(
166 dependentServletContextName)) {
167
168 hasDependencies = false;
169
170 break;
171 }
172 }
173
174 if (hasDependencies) {
175 if (_log.isInfoEnabled()) {
176 _log.info("Deploying " + servletContextName + " from queue");
177 }
178
179 for (HotDeployListener hotDeployListener : _hotDeployListeners) {
180 try {
181 PortletClassLoaderUtil.setClassLoader(
182 hotDeployEvent.getContextClassLoader());
183 PortletClassLoaderUtil.setServletContextName(
184 hotDeployEvent.getServletContextName());
185
186 hotDeployListener.invokeDeploy(hotDeployEvent);
187 }
188 catch (HotDeployException hde) {
189 _log.error(hde, hde);
190 }
191 finally {
192 PortletClassLoaderUtil.setClassLoader(null);
193 PortletClassLoaderUtil.setServletContextName(null);
194 }
195 }
196
197 _deployedServletContextNames.add(servletContextName);
198
199 _dependentHotDeployEvents.remove(hotDeployEvent);
200
201 ClassLoader contextClassLoader = getContextClassLoader();
202
203 try {
204 setContextClassLoader(ClassLoaderUtil.getPortalClassLoader());
205
206 List<HotDeployEvent> dependentEvents =
207 new ArrayList<HotDeployEvent>(_dependentHotDeployEvents);
208
209 for (HotDeployEvent dependentEvent : dependentEvents) {
210 setContextClassLoader(
211 dependentEvent.getContextClassLoader());
212
213 doFireDeployEvent(dependentEvent);
214 }
215 }
216 finally {
217 setContextClassLoader(contextClassLoader);
218 }
219 }
220 else {
221 if (!_dependentHotDeployEvents.contains(hotDeployEvent)) {
222 if (_log.isInfoEnabled()) {
223 StringBundler sb = new StringBundler(4);
224
225 sb.append("Queueing ");
226 sb.append(servletContextName);
227 sb.append(" for deploy because it is missing ");
228 sb.append(getRequiredServletContextNames(hotDeployEvent));
229
230 _log.info(sb.toString());
231 }
232
233 _dependentHotDeployEvents.add(hotDeployEvent);
234 }
235 else {
236 if (_log.isInfoEnabled()) {
237 for (HotDeployEvent dependentHotDeployEvent :
238 _dependentHotDeployEvents) {
239
240 StringBundler sb = new StringBundler(3);
241
242 sb.append(servletContextName);
243 sb.append(" is still in queue because it is missing ");
244 sb.append(
245 getRequiredServletContextNames(
246 dependentHotDeployEvent));
247
248 _log.info(sb.toString());
249 }
250 }
251 }
252 }
253 }
254
255 protected ClassLoader getContextClassLoader() {
256 return ClassLoaderUtil.getContextClassLoader();
257 }
258
259 protected String getRequiredServletContextNames(
260 HotDeployEvent hotDeployEvent) {
261
262 List<String> requiredServletContextNames = new ArrayList<String>();
263
264 for (String dependentServletContextName :
265 hotDeployEvent.getDependentServletContextNames()) {
266
267 if (!_deployedServletContextNames.contains(
268 dependentServletContextName)) {
269
270 requiredServletContextNames.add(dependentServletContextName);
271 }
272 }
273
274 Collections.sort(requiredServletContextNames);
275
276 return StringUtil.merge(requiredServletContextNames, ", ");
277 }
278
279 protected void setContextClassLoader(ClassLoader contextClassLoader) {
280 ClassLoaderUtil.setContextClassLoader(contextClassLoader);
281 }
282
283 private static Log _log = LogFactoryUtil.getLog(HotDeployImpl.class);
284
285 private static PACL _pacl = new NoPACL();
286
287 private boolean _capturePrematureEvents = true;
288 private List<HotDeployEvent> _dependentHotDeployEvents;
289 private Set<String> _deployedServletContextNames;
290 private List<HotDeployListener> _hotDeployListeners;
291
292 private static class NoPACL implements PACL {
293
294 public void initPolicy(
295 String servletContextName, ClassLoader classLoader,
296 Properties properties) {
297 }
298
299 public void unregister(ClassLoader classLoader) {
300 }
301
302 }
303
304 public static interface PACL {
305
306 public void initPolicy(
307 String servletContextName, ClassLoader classLoader,
308 Properties properties);
309
310 public void unregister(ClassLoader classLoader);
311
312 }
313
314 private class HotDeployPortalLifecycle extends BasePortalLifecycle {
315
316 public HotDeployPortalLifecycle(HotDeployEvent hotDeployEvent) {
317 _servletContext = hotDeployEvent.getServletContext();
318 _classLoader = hotDeployEvent.getContextClassLoader();
319
320 ServletContextPool.put(
321 _servletContext.getServletContextName(), _servletContext);
322 }
323
324 @Override
325 protected void doPortalDestroy() {
326 }
327
328 @Override
329 protected void doPortalInit() throws Exception {
330 Properties properties = null;
331
332 String propertiesString = HttpUtil.URLtoString(
333 _servletContext.getResource(
334 "/WEB-INF/liferay-plugin-package.properties"));
335
336 if (propertiesString != null) {
337 properties = PropertiesUtil.load(propertiesString);
338 }
339 else {
340 properties = new Properties();
341 }
342
343 _pacl.initPolicy(
344 _servletContext.getServletContextName(), _classLoader,
345 properties);
346 }
347
348 private ClassLoader _classLoader;
349 private ServletContext _servletContext;
350
351 }
352
353 }