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 public static interface PACL {
161
162 public void initPolicy(
163 String servletContextName, ClassLoader classLoader,
164 Properties properties);
165
166 public void unregister(ClassLoader classLoader);
167
168 }
169
170 protected void doFireDeployEvent(HotDeployEvent hotDeployEvent) {
171 String servletContextName = hotDeployEvent.getServletContextName();
172
173 if (_deployedServletContextNames.contains(servletContextName)) {
174 return;
175 }
176
177 boolean hasDependencies = true;
178
179 for (String dependentServletContextName :
180 hotDeployEvent.getDependentServletContextNames()) {
181
182 if (!_deployedServletContextNames.contains(
183 dependentServletContextName)) {
184
185 hasDependencies = false;
186
187 break;
188 }
189 }
190
191 if (hasDependencies) {
192 if (_log.isInfoEnabled()) {
193 _log.info("Deploying " + servletContextName + " from queue");
194 }
195
196 for (HotDeployListener hotDeployListener : _hotDeployListeners) {
197 try {
198 PortletClassLoaderUtil.setClassLoader(
199 hotDeployEvent.getContextClassLoader());
200 PortletClassLoaderUtil.setServletContextName(
201 hotDeployEvent.getServletContextName());
202
203 hotDeployListener.invokeDeploy(hotDeployEvent);
204 }
205 catch (HotDeployException hde) {
206 _log.error(hde, hde);
207 }
208 finally {
209 PortletClassLoaderUtil.setClassLoader(null);
210 PortletClassLoaderUtil.setServletContextName(null);
211 }
212 }
213
214 _deployedServletContextNames.add(servletContextName);
215
216 _dependentHotDeployEvents.remove(hotDeployEvent);
217
218 ClassLoader contextClassLoader = getContextClassLoader();
219
220 try {
221 setContextClassLoader(ClassLoaderUtil.getPortalClassLoader());
222
223 List<HotDeployEvent> dependentEvents =
224 new ArrayList<HotDeployEvent>(_dependentHotDeployEvents);
225
226 for (HotDeployEvent dependentEvent : dependentEvents) {
227 setContextClassLoader(
228 dependentEvent.getContextClassLoader());
229
230 doFireDeployEvent(dependentEvent);
231 }
232 }
233 finally {
234 setContextClassLoader(contextClassLoader);
235 }
236 }
237 else {
238 if (!_dependentHotDeployEvents.contains(hotDeployEvent)) {
239 if (_log.isInfoEnabled()) {
240 StringBundler sb = new StringBundler(4);
241
242 sb.append("Queueing ");
243 sb.append(servletContextName);
244 sb.append(" for deploy because it is missing ");
245 sb.append(getRequiredServletContextNames(hotDeployEvent));
246
247 _log.info(sb.toString());
248 }
249
250 _dependentHotDeployEvents.add(hotDeployEvent);
251 }
252 else {
253 if (_log.isInfoEnabled()) {
254 for (HotDeployEvent dependentHotDeployEvent :
255 _dependentHotDeployEvents) {
256
257 StringBundler sb = new StringBundler(3);
258
259 sb.append(servletContextName);
260 sb.append(" is still in queue because it is missing ");
261 sb.append(
262 getRequiredServletContextNames(
263 dependentHotDeployEvent));
264
265 _log.info(sb.toString());
266 }
267 }
268 }
269 }
270 }
271
272 protected ClassLoader getContextClassLoader() {
273 return ClassLoaderUtil.getContextClassLoader();
274 }
275
276 protected String getRequiredServletContextNames(
277 HotDeployEvent hotDeployEvent) {
278
279 List<String> requiredServletContextNames = new ArrayList<String>();
280
281 for (String dependentServletContextName :
282 hotDeployEvent.getDependentServletContextNames()) {
283
284 if (!_deployedServletContextNames.contains(
285 dependentServletContextName)) {
286
287 requiredServletContextNames.add(dependentServletContextName);
288 }
289 }
290
291 Collections.sort(requiredServletContextNames);
292
293 return StringUtil.merge(requiredServletContextNames, ", ");
294 }
295
296 protected void setContextClassLoader(ClassLoader contextClassLoader) {
297 ClassLoaderUtil.setContextClassLoader(contextClassLoader);
298 }
299
300 private static Log _log = LogFactoryUtil.getLog(HotDeployImpl.class);
301
302 private static PACL _pacl = new NoPACL();
303
304 private boolean _capturePrematureEvents = true;
305 private List<HotDeployEvent> _dependentHotDeployEvents;
306 private Set<String> _deployedServletContextNames;
307 private List<HotDeployListener> _hotDeployListeners;
308
309 private static class NoPACL implements PACL {
310
311 @Override
312 public void initPolicy(
313 String servletContextName, ClassLoader classLoader,
314 Properties properties) {
315 }
316
317 @Override
318 public void unregister(ClassLoader classLoader) {
319 }
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 }