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.kernel.util.Validator;
035 import com.liferay.portal.util.ClassLoaderUtil;
036
037 import java.util.ArrayList;
038 import java.util.Collections;
039 import java.util.HashSet;
040 import java.util.List;
041 import java.util.Properties;
042 import java.util.Set;
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 ArrayList<HotDeployListener>();
062 }
063
064 @Override
065 public synchronized void fireDeployEvent(
066 final HotDeployEvent hotDeployEvent) {
067
068 PortalLifecycleUtil.register(
069 new HotDeployPortalLifecycle(hotDeployEvent),
070 PortalLifecycle.METHOD_INIT);
071
072 if (_capturePrematureEvents) {
073
074
075
076 PortalLifecycle portalLifecycle = new BasePortalLifecycle() {
077
078 @Override
079 protected void doPortalDestroy() {
080 }
081
082 @Override
083 protected void doPortalInit() {
084 fireDeployEvent(hotDeployEvent);
085 }
086
087 };
088
089 PortalLifecycleUtil.register(
090 portalLifecycle, PortalLifecycle.METHOD_INIT);
091 }
092 else {
093
094
095
096 doFireDeployEvent(hotDeployEvent);
097 }
098 }
099
100 @Override
101 public synchronized void fireUndeployEvent(HotDeployEvent hotDeployEvent) {
102 for (int i = _hotDeployListeners.size() - 1; i >= 0; i--) {
103 HotDeployListener hotDeployListener = _hotDeployListeners.get(i);
104
105 try {
106 PortletClassLoaderUtil.setClassLoader(
107 hotDeployEvent.getContextClassLoader());
108 PortletClassLoaderUtil.setServletContextName(
109 hotDeployEvent.getServletContextName());
110
111 hotDeployListener.invokeUndeploy(hotDeployEvent);
112 }
113 catch (HotDeployException hde) {
114 _log.error(hde, hde);
115 }
116 finally {
117 PortletClassLoaderUtil.setClassLoader(null);
118 PortletClassLoaderUtil.setServletContextName(null);
119 }
120 }
121
122 _deployedServletContextNames.remove(
123 hotDeployEvent.getServletContextName());
124
125 ClassLoader classLoader = hotDeployEvent.getContextClassLoader();
126
127 TemplateManagerUtil.destroy(classLoader);
128
129 _pacl.unregister(classLoader);
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 static 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 try {
225 PortletClassLoaderUtil.setClassLoader(
226 hotDeployEvent.getContextClassLoader());
227 PortletClassLoaderUtil.setServletContextName(
228 hotDeployEvent.getServletContextName());
229
230 hotDeployListener.invokeDeploy(hotDeployEvent);
231 }
232 catch (HotDeployException hde) {
233 _log.error(hde, hde);
234 }
235 finally {
236 PortletClassLoaderUtil.setClassLoader(null);
237 PortletClassLoaderUtil.setServletContextName(null);
238 }
239 }
240
241 _deployedServletContextNames.add(servletContextName);
242
243 _dependentHotDeployEvents.remove(hotDeployEvent);
244
245 ClassLoader contextClassLoader = getContextClassLoader();
246
247 try {
248 setContextClassLoader(ClassLoaderUtil.getPortalClassLoader());
249
250 List<HotDeployEvent> dependentEvents =
251 new ArrayList<HotDeployEvent>(_dependentHotDeployEvents);
252
253 for (HotDeployEvent dependentEvent : dependentEvents) {
254 setContextClassLoader(
255 dependentEvent.getContextClassLoader());
256
257 doFireDeployEvent(dependentEvent);
258
259 dependentEvent.flushInits();
260 }
261 }
262 finally {
263 setContextClassLoader(contextClassLoader);
264 }
265 }
266 else {
267 if (!_dependentHotDeployEvents.contains(hotDeployEvent)) {
268 if (_log.isInfoEnabled()) {
269 StringBundler sb = new StringBundler(4);
270
271 sb.append("Queueing ");
272 sb.append(servletContextName);
273 sb.append(" for deploy because it is missing ");
274 sb.append(getRequiredServletContextNames(hotDeployEvent));
275
276 _log.info(sb.toString());
277 }
278
279 _dependentHotDeployEvents.add(hotDeployEvent);
280 }
281 else {
282 if (_log.isInfoEnabled()) {
283 for (HotDeployEvent dependentHotDeployEvent :
284 _dependentHotDeployEvents) {
285
286 StringBundler sb = new StringBundler(3);
287
288 sb.append(servletContextName);
289 sb.append(" is still in queue because it is missing ");
290 sb.append(
291 getRequiredServletContextNames(
292 dependentHotDeployEvent));
293
294 _log.info(sb.toString());
295 }
296 }
297 }
298 }
299 }
300
301 protected ClassLoader getContextClassLoader() {
302 return ClassLoaderUtil.getContextClassLoader();
303 }
304
305 protected String getRequiredServletContextNames(
306 HotDeployEvent hotDeployEvent) {
307
308 List<String> requiredServletContextNames = new ArrayList<String>();
309
310 for (String dependentServletContextName :
311 hotDeployEvent.getDependentServletContextNames()) {
312
313 if (!_deployedServletContextNames.contains(
314 dependentServletContextName)) {
315
316 requiredServletContextNames.add(dependentServletContextName);
317 }
318 }
319
320 Collections.sort(requiredServletContextNames);
321
322 return StringUtil.merge(requiredServletContextNames, ", ");
323 }
324
325 protected void setContextClassLoader(ClassLoader contextClassLoader) {
326 ClassLoaderUtil.setContextClassLoader(contextClassLoader);
327 }
328
329 private static Log _log = LogFactoryUtil.getLog(HotDeployImpl.class);
330
331 private static PACL _pacl = new NoPACL();
332
333 private boolean _capturePrematureEvents = true;
334 private final List<HotDeployEvent> _dependentHotDeployEvents;
335 private final Set<String> _deployedServletContextNames;
336 private final List<HotDeployListener> _hotDeployListeners;
337
338 private static class NoPACL implements PACL {
339
340 @Override
341 public void initPolicy(
342 String servletContextName, ClassLoader classLoader,
343 Properties properties) {
344 }
345
346 @Override
347 public void unregister(ClassLoader classLoader) {
348 }
349
350 }
351
352 private class HotDeployPortalLifecycle extends BasePortalLifecycle {
353
354 public HotDeployPortalLifecycle(HotDeployEvent hotDeployEvent) {
355 _servletContext = hotDeployEvent.getServletContext();
356 _classLoader = hotDeployEvent.getContextClassLoader();
357
358 ServletContextPool.put(
359 _servletContext.getServletContextName(), _servletContext);
360 }
361
362 @Override
363 protected void doPortalDestroy() {
364 }
365
366 @Override
367 protected void doPortalInit() throws Exception {
368 Properties properties = null;
369
370 String propertiesString = HttpUtil.URLtoString(
371 _servletContext.getResource(
372 "/WEB-INF/liferay-plugin-package.properties"));
373
374 if (propertiesString != null) {
375 properties = PropertiesUtil.load(propertiesString);
376 }
377 else {
378 properties = new Properties();
379 }
380
381 _pacl.initPolicy(
382 _servletContext.getServletContextName(), _classLoader,
383 properties);
384 }
385
386 private ClassLoader _classLoader;
387 private ServletContext _servletContext;
388
389 }
390
391 }