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.freemarker.FreeMarkerEngineUtil;
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.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.velocity.VelocityEngineUtil;
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 import java.util.concurrent.CopyOnWriteArrayList;
044
045 import javax.servlet.ServletContext;
046
047
052 @DoPrivileged
053 public class HotDeployImpl implements HotDeploy {
054
055 public HotDeployImpl() {
056 if (_log.isDebugEnabled()) {
057 _log.debug("Initializing hot deploy manager " + this.hashCode());
058 }
059
060 _dependentHotDeployEvents = new ArrayList<HotDeployEvent>();
061 _deployedServletContextNames = new HashSet<String>();
062 _hotDeployListeners = new CopyOnWriteArrayList<HotDeployListener>();
063 }
064
065 @Override
066 public synchronized void fireDeployEvent(
067 final HotDeployEvent hotDeployEvent) {
068
069 PortalLifecycleUtil.register(
070 new HotDeployPortalLifecycle(hotDeployEvent),
071 PortalLifecycle.METHOD_INIT);
072
073 if (_capturePrematureEvents) {
074
075
076
077 PortalLifecycle portalLifecycle = new BasePortalLifecycle() {
078
079 @Override
080 protected void doPortalDestroy() {
081 }
082
083 @Override
084 protected void doPortalInit() {
085 fireDeployEvent(hotDeployEvent);
086 }
087
088 };
089
090 PortalLifecycleUtil.register(
091 portalLifecycle, PortalLifecycle.METHOD_INIT);
092 }
093 else {
094
095
096
097 doFireDeployEvent(hotDeployEvent);
098 }
099 }
100
101 @Override
102 public synchronized void fireUndeployEvent(HotDeployEvent hotDeployEvent) {
103 for (HotDeployListener hotDeployListener : _hotDeployListeners) {
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 FreeMarkerEngineUtil.clearClassLoader(classLoader);
127 VelocityEngineUtil.clearClassLoader(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 protected void doFireDeployEvent(HotDeployEvent hotDeployEvent) {
163 String servletContextName = hotDeployEvent.getServletContextName();
164
165 if (_deployedServletContextNames.contains(servletContextName)) {
166 return;
167 }
168
169 boolean hasDependencies = true;
170
171 for (String dependentServletContextName :
172 hotDeployEvent.getDependentServletContextNames()) {
173
174 if (!_deployedServletContextNames.contains(
175 dependentServletContextName)) {
176
177 hasDependencies = false;
178
179 break;
180 }
181 }
182
183 if (hasDependencies) {
184 if (_log.isInfoEnabled()) {
185 _log.info("Deploying " + servletContextName + " from queue");
186 }
187
188 for (HotDeployListener hotDeployListener : _hotDeployListeners) {
189 try {
190 PortletClassLoaderUtil.setClassLoader(
191 hotDeployEvent.getContextClassLoader());
192 PortletClassLoaderUtil.setServletContextName(
193 hotDeployEvent.getServletContextName());
194
195 hotDeployListener.invokeDeploy(hotDeployEvent);
196 }
197 catch (HotDeployException hde) {
198 _log.error(hde, hde);
199 }
200 finally {
201 PortletClassLoaderUtil.setClassLoader(null);
202 PortletClassLoaderUtil.setServletContextName(null);
203 }
204 }
205
206 _deployedServletContextNames.add(servletContextName);
207
208 _dependentHotDeployEvents.remove(hotDeployEvent);
209
210 ClassLoader contextClassLoader = getContextClassLoader();
211
212 try {
213 setContextClassLoader(ClassLoaderUtil.getPortalClassLoader());
214
215 List<HotDeployEvent> dependentEvents =
216 new ArrayList<HotDeployEvent>(_dependentHotDeployEvents);
217
218 for (HotDeployEvent dependentEvent : dependentEvents) {
219 setContextClassLoader(
220 dependentEvent.getContextClassLoader());
221
222 doFireDeployEvent(dependentEvent);
223 }
224 }
225 finally {
226 setContextClassLoader(contextClassLoader);
227 }
228 }
229 else {
230 if (!_dependentHotDeployEvents.contains(hotDeployEvent)) {
231 if (_log.isInfoEnabled()) {
232 StringBundler sb = new StringBundler(4);
233
234 sb.append("Queueing ");
235 sb.append(servletContextName);
236 sb.append(" for deploy because it is missing ");
237 sb.append(getRequiredServletContextNames(hotDeployEvent));
238
239 _log.info(sb.toString());
240 }
241
242 _dependentHotDeployEvents.add(hotDeployEvent);
243 }
244 else {
245 if (_log.isInfoEnabled()) {
246 for (HotDeployEvent dependentHotDeployEvent :
247 _dependentHotDeployEvents) {
248
249 StringBundler sb = new StringBundler(3);
250
251 sb.append(servletContextName);
252 sb.append(" is still in queue because it is missing ");
253 sb.append(
254 getRequiredServletContextNames(
255 dependentHotDeployEvent));
256
257 _log.info(sb.toString());
258 }
259 }
260 }
261 }
262 }
263
264 protected ClassLoader getContextClassLoader() {
265 return ClassLoaderUtil.getContextClassLoader();
266 }
267
268 protected String getRequiredServletContextNames(
269 HotDeployEvent hotDeployEvent) {
270
271 List<String> requiredServletContextNames = new ArrayList<String>();
272
273 for (String dependentServletContextName :
274 hotDeployEvent.getDependentServletContextNames()) {
275
276 if (!_deployedServletContextNames.contains(
277 dependentServletContextName)) {
278
279 requiredServletContextNames.add(dependentServletContextName);
280 }
281 }
282
283 Collections.sort(requiredServletContextNames);
284
285 return StringUtil.merge(requiredServletContextNames, ", ");
286 }
287
288 protected void setContextClassLoader(ClassLoader contextClassLoader) {
289 ClassLoaderUtil.setContextClassLoader(contextClassLoader);
290 }
291
292 private static Log _log = LogFactoryUtil.getLog(HotDeployImpl.class);
293
294 private static PACL _pacl = new NoPACL();
295
296 private boolean _capturePrematureEvents = true;
297 private List<HotDeployEvent> _dependentHotDeployEvents;
298 private Set<String> _deployedServletContextNames;
299 private List<HotDeployListener> _hotDeployListeners;
300
301 private static class NoPACL implements PACL {
302
303 @Override
304 public void initPolicy(
305 String servletContextName, ClassLoader classLoader,
306 Properties properties) {
307 }
308
309 @Override
310 public void unregister(ClassLoader classLoader) {
311 }
312
313 }
314
315 public static interface PACL {
316
317 public void initPolicy(
318 String servletContextName, ClassLoader classLoader,
319 Properties properties);
320
321 public void unregister(ClassLoader classLoader);
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 }