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