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
043 import javax.servlet.ServletContext;
044
045
050 @DoPrivileged
051 public class HotDeployImpl implements HotDeploy {
052
053 public HotDeployImpl() {
054 if (_log.isDebugEnabled()) {
055 _log.debug("Initializing hot deploy manager " + this.hashCode());
056 }
057
058 _dependentHotDeployEvents = new ArrayList<HotDeployEvent>();
059 _deployedServletContextNames = new HashSet<String>();
060 _hotDeployListeners = new ArrayList<HotDeployListener>();
061 }
062
063 @Override
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 @Override
100 public synchronized void fireUndeployEvent(HotDeployEvent hotDeployEvent) {
101 for (int i = _hotDeployListeners.size() - 1; i >= 0; i--) {
102 HotDeployListener hotDeployListener = _hotDeployListeners.get(i);
103
104 try {
105 PortletClassLoaderUtil.setClassLoader(
106 hotDeployEvent.getContextClassLoader());
107 PortletClassLoaderUtil.setServletContextName(
108 hotDeployEvent.getServletContextName());
109
110 hotDeployListener.invokeUndeploy(hotDeployEvent);
111 }
112 catch (HotDeployException hde) {
113 _log.error(hde, hde);
114 }
115 finally {
116 PortletClassLoaderUtil.setClassLoader(null);
117 PortletClassLoaderUtil.setServletContextName(null);
118 }
119 }
120
121 _deployedServletContextNames.remove(
122 hotDeployEvent.getServletContextName());
123
124 ClassLoader classLoader = hotDeployEvent.getContextClassLoader();
125
126 TemplateManagerUtil.destroy(classLoader);
127
128 _pacl.unregister(classLoader);
129 }
130
131 @Override
132 public synchronized void registerListener(
133 HotDeployListener hotDeployListener) {
134
135 _hotDeployListeners.add(hotDeployListener);
136 }
137
138 @Override
139 public synchronized void reset() {
140 _capturePrematureEvents = true;
141 _dependentHotDeployEvents.clear();
142 _deployedServletContextNames.clear();
143 _hotDeployListeners.clear();
144 }
145
146 @Override
147 public synchronized void setCapturePrematureEvents(
148 boolean capturePrematureEvents) {
149
150 _capturePrematureEvents = capturePrematureEvents;
151 }
152
153 @Override
154 public synchronized void unregisterListener(
155 HotDeployListener hotDeployListener) {
156
157 _hotDeployListeners.remove(hotDeployListener);
158 }
159
160 @Override
161 public synchronized void unregisterListeners() {
162 _hotDeployListeners.clear();
163 }
164
165 public static interface PACL {
166
167 public void initPolicy(
168 String servletContextName, ClassLoader classLoader,
169 Properties properties);
170
171 public void unregister(ClassLoader classLoader);
172
173 }
174
175 protected void doFireDeployEvent(HotDeployEvent hotDeployEvent) {
176 String servletContextName = hotDeployEvent.getServletContextName();
177
178 if (_deployedServletContextNames.contains(servletContextName)) {
179 return;
180 }
181
182 boolean hasDependencies = true;
183
184 for (String dependentServletContextName :
185 hotDeployEvent.getDependentServletContextNames()) {
186
187 if (!_deployedServletContextNames.contains(
188 dependentServletContextName)) {
189
190 hasDependencies = false;
191
192 break;
193 }
194 }
195
196 if (hasDependencies) {
197 if (_log.isInfoEnabled()) {
198 _log.info("Deploying " + servletContextName + " from queue");
199 }
200
201 for (HotDeployListener hotDeployListener : _hotDeployListeners) {
202 try {
203 PortletClassLoaderUtil.setClassLoader(
204 hotDeployEvent.getContextClassLoader());
205 PortletClassLoaderUtil.setServletContextName(
206 hotDeployEvent.getServletContextName());
207
208 hotDeployListener.invokeDeploy(hotDeployEvent);
209 }
210 catch (HotDeployException hde) {
211 _log.error(hde, hde);
212 }
213 finally {
214 PortletClassLoaderUtil.setClassLoader(null);
215 PortletClassLoaderUtil.setServletContextName(null);
216 }
217 }
218
219 _deployedServletContextNames.add(servletContextName);
220
221 _dependentHotDeployEvents.remove(hotDeployEvent);
222
223 ClassLoader contextClassLoader = getContextClassLoader();
224
225 try {
226 setContextClassLoader(ClassLoaderUtil.getPortalClassLoader());
227
228 List<HotDeployEvent> dependentEvents =
229 new ArrayList<HotDeployEvent>(_dependentHotDeployEvents);
230
231 for (HotDeployEvent dependentEvent : dependentEvents) {
232 setContextClassLoader(
233 dependentEvent.getContextClassLoader());
234
235 doFireDeployEvent(dependentEvent);
236 }
237 }
238 finally {
239 setContextClassLoader(contextClassLoader);
240 }
241 }
242 else {
243 if (!_dependentHotDeployEvents.contains(hotDeployEvent)) {
244 if (_log.isInfoEnabled()) {
245 StringBundler sb = new StringBundler(4);
246
247 sb.append("Queueing ");
248 sb.append(servletContextName);
249 sb.append(" for deploy because it is missing ");
250 sb.append(getRequiredServletContextNames(hotDeployEvent));
251
252 _log.info(sb.toString());
253 }
254
255 _dependentHotDeployEvents.add(hotDeployEvent);
256 }
257 else {
258 if (_log.isInfoEnabled()) {
259 for (HotDeployEvent dependentHotDeployEvent :
260 _dependentHotDeployEvents) {
261
262 StringBundler sb = new StringBundler(3);
263
264 sb.append(servletContextName);
265 sb.append(" is still in queue because it is missing ");
266 sb.append(
267 getRequiredServletContextNames(
268 dependentHotDeployEvent));
269
270 _log.info(sb.toString());
271 }
272 }
273 }
274 }
275 }
276
277 protected ClassLoader getContextClassLoader() {
278 return ClassLoaderUtil.getContextClassLoader();
279 }
280
281 protected String getRequiredServletContextNames(
282 HotDeployEvent hotDeployEvent) {
283
284 List<String> requiredServletContextNames = new ArrayList<String>();
285
286 for (String dependentServletContextName :
287 hotDeployEvent.getDependentServletContextNames()) {
288
289 if (!_deployedServletContextNames.contains(
290 dependentServletContextName)) {
291
292 requiredServletContextNames.add(dependentServletContextName);
293 }
294 }
295
296 Collections.sort(requiredServletContextNames);
297
298 return StringUtil.merge(requiredServletContextNames, ", ");
299 }
300
301 protected void setContextClassLoader(ClassLoader contextClassLoader) {
302 ClassLoaderUtil.setContextClassLoader(contextClassLoader);
303 }
304
305 private static Log _log = LogFactoryUtil.getLog(HotDeployImpl.class);
306
307 private static PACL _pacl = new NoPACL();
308
309 private boolean _capturePrematureEvents = true;
310 private final List<HotDeployEvent> _dependentHotDeployEvents;
311 private final Set<String> _deployedServletContextNames;
312 private final List<HotDeployListener> _hotDeployListeners;
313
314 private static class NoPACL implements PACL {
315
316 @Override
317 public void initPolicy(
318 String servletContextName, ClassLoader classLoader,
319 Properties properties) {
320 }
321
322 @Override
323 public void unregister(ClassLoader classLoader) {
324 }
325
326 }
327
328 private class HotDeployPortalLifecycle extends BasePortalLifecycle {
329
330 public HotDeployPortalLifecycle(HotDeployEvent hotDeployEvent) {
331 _servletContext = hotDeployEvent.getServletContext();
332 _classLoader = hotDeployEvent.getContextClassLoader();
333
334 ServletContextPool.put(
335 _servletContext.getServletContextName(), _servletContext);
336 }
337
338 @Override
339 protected void doPortalDestroy() {
340 }
341
342 @Override
343 protected void doPortalInit() throws Exception {
344 Properties properties = null;
345
346 String propertiesString = HttpUtil.URLtoString(
347 _servletContext.getResource(
348 "/WEB-INF/liferay-plugin-package.properties"));
349
350 if (propertiesString != null) {
351 properties = PropertiesUtil.load(propertiesString);
352 }
353 else {
354 properties = new Properties();
355 }
356
357 _pacl.initPolicy(
358 _servletContext.getServletContextName(), _classLoader,
359 properties);
360 }
361
362 private ClassLoader _classLoader;
363 private ServletContext _servletContext;
364
365 }
366
367 }