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