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.servlet.ServletContextPool;
026 import com.liferay.portal.kernel.util.BasePortalLifecycle;
027 import com.liferay.portal.kernel.util.HttpUtil;
028 import com.liferay.portal.kernel.util.PortalLifecycle;
029 import com.liferay.portal.kernel.util.PortalLifecycleUtil;
030 import com.liferay.portal.kernel.util.PropertiesUtil;
031 import com.liferay.portal.kernel.util.StringBundler;
032 import com.liferay.portal.kernel.util.StringUtil;
033 import com.liferay.portal.kernel.velocity.VelocityEngineUtil;
034 import com.liferay.portal.security.pacl.PACLClassLoaderUtil;
035 import com.liferay.portal.security.pacl.PACLPolicy;
036 import com.liferay.portal.security.pacl.PACLPolicyManager;
037
038 import java.util.ArrayList;
039 import java.util.Collections;
040 import java.util.HashSet;
041 import java.util.List;
042 import java.util.Properties;
043 import java.util.Set;
044 import java.util.concurrent.CopyOnWriteArrayList;
045
046 import javax.servlet.ServletContext;
047
048
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 public synchronized void fireDeployEvent(
066 final HotDeployEvent hotDeployEvent) {
067
068 PortalLifecycleUtil.register(
069 new PACLPortalLifecycle(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 public synchronized void fireUndeployEvent(HotDeployEvent hotDeployEvent) {
101 for (HotDeployListener hotDeployListener : _hotDeployListeners) {
102 try {
103 PortletClassLoaderUtil.setClassLoader(
104 hotDeployEvent.getContextClassLoader());
105 PortletClassLoaderUtil.setServletContextName(
106 hotDeployEvent.getServletContextName());
107
108 hotDeployListener.invokeUndeploy(hotDeployEvent);
109 }
110 catch (HotDeployException hde) {
111 _log.error(hde, hde);
112 }
113 finally {
114 PortletClassLoaderUtil.setClassLoader(null);
115 PortletClassLoaderUtil.setServletContextName(null);
116 }
117 }
118
119 _deployedServletContextNames.remove(
120 hotDeployEvent.getServletContextName());
121
122 ClassLoader classLoader = hotDeployEvent.getContextClassLoader();
123
124 FreeMarkerEngineUtil.clearClassLoader(classLoader);
125 VelocityEngineUtil.clearClassLoader(classLoader);
126
127 PACLPolicyManager.unregister(classLoader);
128 }
129
130 public void registerListener(HotDeployListener hotDeployListener) {
131 _hotDeployListeners.add(hotDeployListener);
132 }
133
134 public synchronized void reset() {
135 _capturePrematureEvents = true;
136 _dependentHotDeployEvents.clear();
137 _deployedServletContextNames.clear();
138 _hotDeployListeners.clear();
139 }
140
141 public synchronized void setCapturePrematureEvents(
142 boolean capturePrematureEvents) {
143
144 _capturePrematureEvents = capturePrematureEvents;
145 }
146
147 public void unregisterListener(HotDeployListener hotDeployListener) {
148 _hotDeployListeners.remove(hotDeployListener);
149 }
150
151 public void unregisterListeners() {
152 _hotDeployListeners.clear();
153 }
154
155 protected void doFireDeployEvent(HotDeployEvent hotDeployEvent) {
156 String servletContextName = hotDeployEvent.getServletContextName();
157
158 if (_deployedServletContextNames.contains(servletContextName)) {
159 return;
160 }
161
162 boolean hasDependencies = true;
163
164 for (String dependentServletContextName :
165 hotDeployEvent.getDependentServletContextNames()) {
166
167 if (!_deployedServletContextNames.contains(
168 dependentServletContextName)) {
169
170 hasDependencies = false;
171
172 break;
173 }
174 }
175
176 if (hasDependencies) {
177 if (_log.isInfoEnabled()) {
178 _log.info("Deploying " + servletContextName + " from queue");
179 }
180
181 for (HotDeployListener hotDeployListener : _hotDeployListeners) {
182 try {
183 PortletClassLoaderUtil.setClassLoader(
184 hotDeployEvent.getContextClassLoader());
185 PortletClassLoaderUtil.setServletContextName(
186 hotDeployEvent.getServletContextName());
187
188 hotDeployListener.invokeDeploy(hotDeployEvent);
189 }
190 catch (HotDeployException hde) {
191 _log.error(hde, hde);
192 }
193 finally {
194 PortletClassLoaderUtil.setClassLoader(null);
195 PortletClassLoaderUtil.setServletContextName(null);
196 }
197 }
198
199 _deployedServletContextNames.add(servletContextName);
200
201 _dependentHotDeployEvents.remove(hotDeployEvent);
202
203 ClassLoader contextClassLoader = getContextClassLoader();
204
205 try {
206 setContextClassLoader(
207 PACLClassLoaderUtil.getPortalClassLoader());
208
209 List<HotDeployEvent> dependentEvents =
210 new ArrayList<HotDeployEvent>(_dependentHotDeployEvents);
211
212 for (HotDeployEvent dependentEvent : dependentEvents) {
213 setContextClassLoader(
214 dependentEvent.getContextClassLoader());
215
216 doFireDeployEvent(dependentEvent);
217 }
218 }
219 finally {
220 setContextClassLoader(contextClassLoader);
221 }
222 }
223 else {
224 if (!_dependentHotDeployEvents.contains(hotDeployEvent)) {
225 if (_log.isInfoEnabled()) {
226 StringBundler sb = new StringBundler(4);
227
228 sb.append("Queueing ");
229 sb.append(servletContextName);
230 sb.append(" for deploy because it is missing ");
231 sb.append(getRequiredServletContextNames(hotDeployEvent));
232
233 _log.info(sb.toString());
234 }
235
236 _dependentHotDeployEvents.add(hotDeployEvent);
237 }
238 else {
239 if (_log.isInfoEnabled()) {
240 for (HotDeployEvent dependentHotDeployEvent :
241 _dependentHotDeployEvents) {
242
243 StringBundler sb = new StringBundler(3);
244
245 sb.append(servletContextName);
246 sb.append(" is still in queue because it is missing ");
247 sb.append(
248 getRequiredServletContextNames(
249 dependentHotDeployEvent));
250
251 _log.info(sb.toString());
252 }
253 }
254 }
255 }
256 }
257
258 protected ClassLoader getContextClassLoader() {
259 return PACLClassLoaderUtil.getContextClassLoader();
260 }
261
262 protected String getRequiredServletContextNames(
263 HotDeployEvent hotDeployEvent) {
264
265 List<String> requiredServletContextNames = new ArrayList<String>();
266
267 for (String dependentServletContextName :
268 hotDeployEvent.getDependentServletContextNames()) {
269
270 if (!_deployedServletContextNames.contains(
271 dependentServletContextName)) {
272
273 requiredServletContextNames.add(dependentServletContextName);
274 }
275 }
276
277 Collections.sort(requiredServletContextNames);
278
279 return StringUtil.merge(requiredServletContextNames, ", ");
280 }
281
282 protected void setContextClassLoader(ClassLoader contextClassLoader) {
283 PACLClassLoaderUtil.setContextClassLoader(contextClassLoader);
284 }
285
286 private static Log _log = LogFactoryUtil.getLog(HotDeployImpl.class);
287
288 private boolean _capturePrematureEvents = true;
289 private List<HotDeployEvent> _dependentHotDeployEvents;
290 private Set<String> _deployedServletContextNames;
291 private List<HotDeployListener> _hotDeployListeners;
292
293 private class PACLPortalLifecycle extends BasePortalLifecycle {
294
295 public PACLPortalLifecycle(HotDeployEvent hotDeployEvent) {
296 _servletContext = hotDeployEvent.getServletContext();
297 _classLoader = hotDeployEvent.getContextClassLoader();
298
299 ServletContextPool.put(
300 _servletContext.getServletContextName(), _servletContext);
301 }
302
303 @Override
304 protected void doPortalDestroy() {
305 }
306
307 @Override
308 protected void doPortalInit() throws Exception {
309 Properties properties = null;
310
311 String propertiesString = HttpUtil.URLtoString(
312 _servletContext.getResource(
313 "/WEB-INF/liferay-plugin-package.properties"));
314
315 if (propertiesString != null) {
316 properties = PropertiesUtil.load(propertiesString);
317 }
318 else {
319 properties = new Properties();
320 }
321
322 PACLPolicy paclPolicy = PACLPolicyManager.buildPACLPolicy(
323 _servletContext.getServletContextName(), _classLoader,
324 properties);
325
326 PACLPolicyManager.register(_classLoader, paclPolicy);
327 }
328
329 private ClassLoader _classLoader;
330 private ServletContext _servletContext;
331
332 };
333
334 }