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