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