1
14
15 package com.liferay.portal.deploy.hot;
16
17 import com.liferay.portal.apache.bridges.struts.LiferayServletContextProvider;
18 import com.liferay.portal.kernel.configuration.Configuration;
19 import com.liferay.portal.kernel.configuration.ConfigurationFactoryUtil;
20 import com.liferay.portal.kernel.deploy.hot.BaseHotDeployListener;
21 import com.liferay.portal.kernel.deploy.hot.HotDeployEvent;
22 import com.liferay.portal.kernel.deploy.hot.HotDeployException;
23 import com.liferay.portal.kernel.job.Scheduler;
24 import com.liferay.portal.kernel.language.LanguageUtil;
25 import com.liferay.portal.kernel.log.Log;
26 import com.liferay.portal.kernel.log.LogFactoryUtil;
27 import com.liferay.portal.kernel.portlet.PortletBag;
28 import com.liferay.portal.kernel.search.Indexer;
29 import com.liferay.portal.kernel.search.IndexerRegistryUtil;
30 import com.liferay.portal.kernel.servlet.PortletServlet;
31 import com.liferay.portal.kernel.servlet.ServletContextProvider;
32 import com.liferay.portal.kernel.util.ClassUtil;
33 import com.liferay.portal.kernel.util.GetterUtil;
34 import com.liferay.portal.kernel.util.HttpUtil;
35 import com.liferay.portal.kernel.util.LocaleUtil;
36 import com.liferay.portal.kernel.util.ObjectValuePair;
37 import com.liferay.portal.kernel.util.PropsKeys;
38 import com.liferay.portal.kernel.util.StringUtil;
39 import com.liferay.portal.kernel.util.Validator;
40 import com.liferay.portal.model.Portlet;
41 import com.liferay.portal.model.PortletApp;
42 import com.liferay.portal.model.PortletCategory;
43 import com.liferay.portal.model.PortletFilter;
44 import com.liferay.portal.model.PortletURLListener;
45 import com.liferay.portal.poller.PollerProcessorUtil;
46 import com.liferay.portal.pop.POPServerUtil;
47 import com.liferay.portal.security.permission.ResourceActionsUtil;
48 import com.liferay.portal.service.PortletLocalServiceUtil;
49 import com.liferay.portal.service.ResourceActionLocalServiceUtil;
50 import com.liferay.portal.service.ResourceCodeLocalServiceUtil;
51 import com.liferay.portal.util.Portal;
52 import com.liferay.portal.util.PortalInstances;
53 import com.liferay.portal.util.WebAppPool;
54 import com.liferay.portal.util.WebKeys;
55 import com.liferay.portal.webdav.WebDAVUtil;
56 import com.liferay.portlet.CustomUserAttributes;
57 import com.liferay.portlet.InvokerPortlet;
58 import com.liferay.portlet.PortletBagFactory;
59 import com.liferay.portlet.PortletContextBag;
60 import com.liferay.portlet.PortletContextBagPool;
61 import com.liferay.portlet.PortletFilterFactory;
62 import com.liferay.portlet.PortletInstanceFactoryUtil;
63 import com.liferay.portlet.PortletResourceBundles;
64 import com.liferay.portlet.PortletURLListenerFactory;
65 import com.liferay.portlet.social.service.SocialActivityInterpreterLocalServiceUtil;
66 import com.liferay.portlet.social.service.SocialRequestInterpreterLocalServiceUtil;
67 import com.liferay.util.log4j.Log4JUtil;
68
69 import java.util.HashMap;
70 import java.util.HashSet;
71 import java.util.Iterator;
72 import java.util.List;
73 import java.util.Locale;
74 import java.util.Map;
75 import java.util.Properties;
76 import java.util.ResourceBundle;
77 import java.util.Set;
78
79 import javax.portlet.PortletURLGenerationListener;
80
81 import javax.servlet.ServletContext;
82
83 import org.apache.portals.bridges.struts.StrutsPortlet;
84
85
93 public class PortletHotDeployListener extends BaseHotDeployListener {
94
95 public void invokeDeploy(HotDeployEvent event) throws HotDeployException {
96 try {
97 doInvokeDeploy(event);
98 }
99 catch (Throwable t) {
100 throwHotDeployException(
101 event, "Error registering portlets for ", t);
102 }
103 }
104
105 public void invokeUndeploy(HotDeployEvent event) throws HotDeployException {
106 try {
107 doInvokeUndeploy(event);
108 }
109 catch (Throwable t) {
110 throwHotDeployException(
111 event, "Error unregistering portlets for ", t);
112 }
113 }
114
115 protected void destroyPortlet(Portlet portlet, Set<String> portletIds)
116 throws Exception {
117
118 PortletApp portletApp = portlet.getPortletApp();
119
120 Set<PortletFilter> portletFilters = portletApp.getPortletFilters();
121
122 for (PortletFilter portletFilter : portletFilters) {
123 PortletFilterFactory.destroy(portletFilter);
124 }
125
126 Set<PortletURLListener> portletURLListeners =
127 portletApp.getPortletURLListeners();
128
129 for (PortletURLListener portletURLListener : portletURLListeners) {
130 PortletURLListenerFactory.destroy(portletURLListener);
131 }
132
133 Indexer indexer = portlet.getIndexerInstance();
134
135 if (indexer != null) {
136 IndexerRegistryUtil.unregister(indexer);
137 }
138
139 Scheduler scheduler = portlet.getSchedulerInstance();
140
141 if (scheduler != null) {
142 scheduler.unschedule();
143 }
144
145 PollerProcessorUtil.deletePollerProcessor(portlet.getPortletId());
146
147 POPServerUtil.deleteListener(portlet.getPopMessageListenerInstance());
148
149 SocialActivityInterpreterLocalServiceUtil.deleteActivityInterpreter(
150 portlet.getSocialActivityInterpreterInstance());
151
152 SocialRequestInterpreterLocalServiceUtil.deleteRequestInterpreter(
153 portlet.getSocialRequestInterpreterInstance());
154
155 WebDAVUtil.deleteStorage(portlet.getWebDAVStorageInstance());
156
157 PortletInstanceFactoryUtil.destroy(portlet);
158
159 portletIds.add(portlet.getPortletId());
160 }
161
162 protected void doInvokeDeploy(HotDeployEvent event) throws Exception {
163
164
166 ServletContext servletContext = event.getServletContext();
167
168 String servletContextName = servletContext.getServletContextName();
169
170 if (_log.isDebugEnabled()) {
171 _log.debug("Invoking deploy for " + servletContextName);
172 }
173
174
176 long[] companyIds = PortalInstances.getCompanyIds();
177
178
180 String[] xmls = new String[] {
181 HttpUtil.URLtoString(
182 servletContext.getResource(
183 "/WEB-INF/" + Portal.PORTLET_XML_FILE_NAME_STANDARD)),
184 HttpUtil.URLtoString(
185 servletContext.getResource(
186 "/WEB-INF/" + Portal.PORTLET_XML_FILE_NAME_CUSTOM)),
187 HttpUtil.URLtoString(
188 servletContext.getResource("/WEB-INF/liferay-portlet.xml")),
189 HttpUtil.URLtoString(servletContext.getResource("/WEB-INF/web.xml"))
190 };
191
192 if (xmls[0] == null) {
193 return;
194 }
195
196 if (_log.isInfoEnabled()) {
197 _log.info("Registering portlets for " + servletContextName);
198 }
199
200 List<Portlet> portlets = PortletLocalServiceUtil.initWAR(
201 servletContextName, servletContext, xmls, event.getPluginPackage());
202
203
205 ClassLoader portletClassLoader = event.getContextClassLoader();
206
207 servletContext.setAttribute(
208 PortletServlet.PORTLET_CLASS_LOADER, portletClassLoader);
209
210
212 initLogger(portletClassLoader);
213
214
216 _portletAppInitialized = false;
217 _strutsBridges = false;
218
219 PortletBagFactory portletBagFactory = new PortletBagFactory();
220
221 portletBagFactory.setClassLoader(portletClassLoader);
222 portletBagFactory.setServletContext(servletContext);
223 portletBagFactory.setWARFile(true);
224
225 Iterator<Portlet> itr = portlets.iterator();
226
227 while (itr.hasNext()) {
228 Portlet portlet = itr.next();
229
230 PortletBag portletBag = initPortlet(portlet, portletBagFactory);
231
232 if (portletBag == null) {
233 itr.remove();
234 }
235 else {
236 if (!_portletAppInitialized) {
237 initPortletApp(
238 portlet, servletContextName, servletContext,
239 portletClassLoader);
240
241 _portletAppInitialized = true;
242 }
243 }
244 }
245
246
248 if (!_strutsBridges) {
249 _strutsBridges = GetterUtil.getBoolean(
250 servletContext.getInitParameter(
251 "struts-bridges-context-provider"));
252 }
253
254 if (_strutsBridges) {
255 servletContext.setAttribute(
256 ServletContextProvider.STRUTS_BRIDGES_CONTEXT_PROVIDER,
257 new LiferayServletContextProvider());
258 }
259
260
262 String xml = HttpUtil.URLtoString(
263 servletContext.getResource("/WEB-INF/liferay-display.xml"));
264
265 PortletCategory newPortletCategory =
266 PortletLocalServiceUtil.getWARDisplay(servletContextName, xml);
267
268 for (int i = 0; i < companyIds.length; i++) {
269 long companyId = companyIds[i];
270
271 PortletCategory portletCategory =
272 (PortletCategory)WebAppPool.get(
273 String.valueOf(companyId), WebKeys.PORTLET_CATEGORY);
274
275 if (portletCategory != null) {
276 portletCategory.merge(newPortletCategory);
277 }
278 else {
279 _log.error(
280 "Unable to register portlet for company " + companyId +
281 " because it does not exist");
282 }
283 }
284
285
287 processPortletProperties(servletContextName, portletClassLoader);
288
289
291 itr = portlets.iterator();
292
293 while (itr.hasNext()) {
294 Portlet portlet = itr.next();
295
296 List<String> modelNames =
297 ResourceActionsUtil.getPortletModelResources(
298 portlet.getPortletId());
299
300 for (long companyId : companyIds) {
301 ResourceCodeLocalServiceUtil.checkResourceCodes(
302 companyId, portlet.getPortletId());
303
304 for (String modelName : modelNames) {
305 ResourceCodeLocalServiceUtil.checkResourceCodes(
306 companyId, modelName);
307 }
308 }
309
310 List<String> portletActions =
311 ResourceActionsUtil.getPortletResourceActions(
312 portlet.getPortletId());
313
314 ResourceActionLocalServiceUtil.checkResourceActions(
315 portlet.getPortletId(), portletActions);
316
317 for (String modelName : modelNames) {
318 List<String> modelActions =
319 ResourceActionsUtil.getModelResourceActions(modelName);
320
321 ResourceActionLocalServiceUtil.checkResourceActions(
322 modelName, modelActions);
323 }
324 }
325
326
328 for (Portlet portlet : portlets) {
329 boolean ready = GetterUtil.getBoolean(
330 servletContext.getInitParameter(
331 "portlets-ready-by-default"), true);
332
333 portlet.setReady(ready);
334 }
335
336
338 registerClpMessageListeners(servletContext, portletClassLoader);
339
340
342 _vars.put(
343 servletContextName,
344 new ObjectValuePair<long[], List<Portlet>>(
345 companyIds, portlets));
346
347 if (_log.isInfoEnabled()) {
348 if (portlets.size() == 1) {
349 _log.info(
350 "1 portlet for " + servletContextName +
351 " is available for use");
352 }
353 else {
354 _log.info(
355 portlets.size() + " portlets for " + servletContextName +
356 " are available for use");
357 }
358 }
359 }
360
361 protected void doInvokeUndeploy(HotDeployEvent event) throws Exception {
362 ServletContext servletContext = event.getServletContext();
363
364 String servletContextName = servletContext.getServletContextName();
365
366 if (_log.isDebugEnabled()) {
367 _log.debug("Invoking undeploy for " + servletContextName);
368 }
369
370 ObjectValuePair<long[], List<Portlet>> ovp =
371 _vars.remove(servletContextName);
372
373 if (ovp == null) {
374 return;
375 }
376
377 long[] companyIds = ovp.getKey();
378 List<Portlet> portlets = ovp.getValue();
379
380 Set<String> portletIds = new HashSet<String>();
381
382 if (portlets != null) {
383 if (_log.isInfoEnabled()) {
384 _log.info(
385 "Unregistering portlets for " + servletContextName);
386 }
387
388 Iterator<Portlet> itr = portlets.iterator();
389
390 while (itr.hasNext()) {
391 Portlet portlet = itr.next();
392
393 destroyPortlet(portlet, portletIds);
394 }
395 }
396
397 if (portletIds.size() > 0) {
398 for (int i = 0; i < companyIds.length; i++) {
399 long companyId = companyIds[i];
400
401 PortletCategory portletCategory =
402 (PortletCategory)WebAppPool.get(
403 String.valueOf(companyId), WebKeys.PORTLET_CATEGORY);
404
405 portletCategory.separate(portletIds);
406 }
407 }
408
409 PortletResourceBundles.remove(servletContextName);
410
411 unregisterClpMessageListeners(servletContext);
412
413 if (_log.isInfoEnabled()) {
414 if (portlets.size() == 1) {
415 _log.info(
416 "1 portlet for " + servletContextName +
417 " was unregistered");
418 }
419 else {
420 _log.info(
421 portlets.size() + " portlets for " + servletContextName +
422 " was unregistered");
423 }
424 }
425 }
426
427 protected void initLogger(ClassLoader portletClassLoader) {
428 Log4JUtil.configureLog4J(
429 portletClassLoader.getResource("META-INF/portal-log4j.xml"));
430 }
431
432 protected PortletBag initPortlet(
433 Portlet portlet, PortletBagFactory portletBagFactory)
434 throws Exception {
435
436 PortletBag portletBag = portletBagFactory.create(portlet);
437
438 if (portletBag == null) {
439 return null;
440 }
441
442 javax.portlet.Portlet portletInstance = portletBag.getPortletInstance();
443
444 if (ClassUtil.isSubclass(
445 portletInstance.getClass(), StrutsPortlet.class.getName())) {
446
447 _strutsBridges = true;
448 }
449
450 return portletBag;
451 }
452
453 protected void initPortletApp(
454 Portlet portlet, String servletContextName,
455 ServletContext servletContext, ClassLoader portletClassLoader)
456 throws Exception {
457
458 PortletContextBag portletContextBag = new PortletContextBag(
459 servletContextName);
460
461 PortletContextBagPool.put(servletContextName, portletContextBag);
462
463 PortletApp portletApp = portlet.getPortletApp();
464
465 servletContext.setAttribute(PortletServlet.PORTLET_APP, portletApp);
466
467 Map<String, String> customUserAttributes =
468 portletApp.getCustomUserAttributes();
469
470 for (Map.Entry<String, String> entry :
471 customUserAttributes.entrySet()) {
472
473 String attrCustomClass = entry.getValue();
474
475 CustomUserAttributes customUserAttributesInstance =
476 (CustomUserAttributes)portletClassLoader.loadClass(
477 attrCustomClass).newInstance();
478
479 portletContextBag.getCustomUserAttributes().put(
480 attrCustomClass, customUserAttributesInstance);
481 }
482
483 Set<PortletFilter> portletFilters = portletApp.getPortletFilters();
484
485 for (PortletFilter portletFilter : portletFilters) {
486 javax.portlet.filter.PortletFilter portletFilterInstance =
487 (javax.portlet.filter.PortletFilter)newInstance(
488 portletClassLoader,
489 new Class<?>[] {
490 javax.portlet.filter.ActionFilter.class,
491 javax.portlet.filter.EventFilter.class,
492 javax.portlet.filter.PortletFilter.class,
493 javax.portlet.filter.RenderFilter.class,
494 javax.portlet.filter.ResourceFilter.class
495 },
496 portletFilter.getFilterClass());
497
498 portletContextBag.getPortletFilters().put(
499 portletFilter.getFilterName(), portletFilterInstance);
500 }
501
502 InvokerPortlet invokerPortlet = PortletInstanceFactoryUtil.create(
503 portlet, servletContext);
504
505 invokerPortlet.setPortletFilters();
506
507 Set<PortletURLListener> portletURLListeners =
508 portletApp.getPortletURLListeners();
509
510 for (PortletURLListener portletURLListener : portletURLListeners) {
511 PortletURLGenerationListener portletURLListenerInstance =
512 (PortletURLGenerationListener)newInstance(
513 portletClassLoader, PortletURLGenerationListener.class,
514 portletURLListener.getListenerClass());
515
516 portletContextBag.getPortletURLListeners().put(
517 portletURLListener.getListenerClass(),
518 portletURLListenerInstance);
519
520 PortletURLListenerFactory.create(portletURLListener);
521 }
522 }
523
524 protected void processPortletProperties(
525 String servletContextName, ClassLoader portletClassLoader)
526 throws Exception {
527
528 Configuration portletPropertiesConfiguration = null;
529
530 try {
531 portletPropertiesConfiguration =
532 ConfigurationFactoryUtil.getConfiguration(
533 portletClassLoader, "portlet");
534 }
535 catch (Exception e) {
536 if (_log.isDebugEnabled()) {
537 _log.debug("Unable to read portlet.properties");
538 }
539
540 return;
541 }
542
543 Properties portletProperties =
544 portletPropertiesConfiguration.getProperties();
545
546 if (portletProperties.size() == 0) {
547 return;
548 }
549
550 String languageBundleName = portletProperties.getProperty(
551 "language.bundle");
552
553 if (Validator.isNotNull(languageBundleName)) {
554 Locale[] locales = LanguageUtil.getAvailableLocales();
555
556 for (int i = 0; i < locales.length; i++) {
557 ResourceBundle resourceBundle = ResourceBundle.getBundle(
558 languageBundleName, locales[i], portletClassLoader);
559
560 PortletResourceBundles.put(
561 servletContextName, LocaleUtil.toLanguageId(locales[i]),
562 resourceBundle);
563 }
564 }
565
566 String[] resourceActionConfigs = StringUtil.split(
567 portletProperties.getProperty(PropsKeys.RESOURCE_ACTIONS_CONFIGS));
568
569 for (int i = 0; i < resourceActionConfigs.length; i++) {
570 ResourceActionsUtil.read(
571 servletContextName, portletClassLoader,
572 resourceActionConfigs[i]);
573 }
574 }
575
576 private static Log _log = LogFactoryUtil.getLog(
577 PortletHotDeployListener.class);
578
579 private static Map<String, ObjectValuePair<long[], List<Portlet>>> _vars =
580 new HashMap<String, ObjectValuePair<long[], List<Portlet>>>();
581
582 private boolean _portletAppInitialized;
583 private boolean _strutsBridges;
584
585 }