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