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