001
014
015 package com.liferay.portal.deploy.hot;
016
017 import com.liferay.portal.apache.bridges.struts.LiferayServletContextProvider;
018 import com.liferay.portal.kernel.atom.AtomCollectionAdapter;
019 import com.liferay.portal.kernel.atom.AtomCollectionAdapterRegistryUtil;
020 import com.liferay.portal.kernel.concurrent.LockRegistry;
021 import com.liferay.portal.kernel.configuration.Configuration;
022 import com.liferay.portal.kernel.configuration.ConfigurationFactoryUtil;
023 import com.liferay.portal.kernel.deploy.hot.BaseHotDeployListener;
024 import com.liferay.portal.kernel.deploy.hot.HotDeployEvent;
025 import com.liferay.portal.kernel.deploy.hot.HotDeployException;
026 import com.liferay.portal.kernel.language.LanguageUtil;
027 import com.liferay.portal.kernel.log.Log;
028 import com.liferay.portal.kernel.log.LogFactoryUtil;
029 import com.liferay.portal.kernel.portlet.PortletBag;
030 import com.liferay.portal.kernel.scheduler.SchedulerEngineUtil;
031 import com.liferay.portal.kernel.scheduler.SchedulerEntry;
032 import com.liferay.portal.kernel.scheduler.StorageType;
033 import com.liferay.portal.kernel.search.Indexer;
034 import com.liferay.portal.kernel.search.IndexerRegistryUtil;
035 import com.liferay.portal.kernel.servlet.DirectServletRegistry;
036 import com.liferay.portal.kernel.servlet.FileTimestampUtil;
037 import com.liferay.portal.kernel.servlet.PortletServlet;
038 import com.liferay.portal.kernel.servlet.ServletContextPool;
039 import com.liferay.portal.kernel.servlet.ServletContextProvider;
040 import com.liferay.portal.kernel.util.ClassUtil;
041 import com.liferay.portal.kernel.util.GetterUtil;
042 import com.liferay.portal.kernel.util.HttpUtil;
043 import com.liferay.portal.kernel.util.LocaleUtil;
044 import com.liferay.portal.kernel.util.ObjectValuePair;
045 import com.liferay.portal.kernel.util.PropsKeys;
046 import com.liferay.portal.kernel.util.StringUtil;
047 import com.liferay.portal.kernel.util.Validator;
048 import com.liferay.portal.kernel.webdav.WebDAVUtil;
049 import com.liferay.portal.kernel.workflow.WorkflowHandler;
050 import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil;
051 import com.liferay.portal.model.Portlet;
052 import com.liferay.portal.model.PortletApp;
053 import com.liferay.portal.model.PortletCategory;
054 import com.liferay.portal.model.PortletFilter;
055 import com.liferay.portal.model.PortletURLListener;
056 import com.liferay.portal.poller.PollerProcessorUtil;
057 import com.liferay.portal.pop.POPServerUtil;
058 import com.liferay.portal.security.permission.ResourceActionsUtil;
059 import com.liferay.portal.service.PortletLocalServiceUtil;
060 import com.liferay.portal.service.ResourceActionLocalServiceUtil;
061 import com.liferay.portal.service.ResourceCodeLocalServiceUtil;
062 import com.liferay.portal.spring.context.PortletContextLoader;
063 import com.liferay.portal.spring.context.PortletContextLoaderListener;
064 import com.liferay.portal.util.Portal;
065 import com.liferay.portal.util.PortalInstances;
066 import com.liferay.portal.util.PropsValues;
067 import com.liferay.portal.util.WebAppPool;
068 import com.liferay.portal.util.WebKeys;
069 import com.liferay.portal.xmlrpc.XmlRpcServlet;
070 import com.liferay.portlet.CustomUserAttributes;
071 import com.liferay.portlet.InvokerPortlet;
072 import com.liferay.portlet.PortletBagFactory;
073 import com.liferay.portlet.PortletContextBag;
074 import com.liferay.portlet.PortletContextBagPool;
075 import com.liferay.portlet.PortletFilterFactory;
076 import com.liferay.portlet.PortletInstanceFactoryUtil;
077 import com.liferay.portlet.PortletResourceBundles;
078 import com.liferay.portlet.PortletURLListenerFactory;
079 import com.liferay.portlet.asset.AssetRendererFactoryRegistryUtil;
080 import com.liferay.portlet.asset.model.AssetRendererFactory;
081 import com.liferay.portlet.social.service.SocialActivityInterpreterLocalServiceUtil;
082 import com.liferay.portlet.social.service.SocialRequestInterpreterLocalServiceUtil;
083 import com.liferay.util.log4j.Log4JUtil;
084
085 import java.util.HashMap;
086 import java.util.HashSet;
087 import java.util.Iterator;
088 import java.util.List;
089 import java.util.Locale;
090 import java.util.Map;
091 import java.util.Properties;
092 import java.util.ResourceBundle;
093 import java.util.Set;
094 import java.util.concurrent.locks.Lock;
095
096 import javax.portlet.PortletURLGenerationListener;
097
098 import javax.servlet.ServletContext;
099
100 import org.apache.portals.bridges.struts.StrutsPortlet;
101
102
108 public class PortletHotDeployListener extends BaseHotDeployListener {
109
110 public void invokeDeploy(HotDeployEvent hotDeployEvent)
111 throws HotDeployException {
112
113 try {
114 doInvokeDeploy(hotDeployEvent);
115 }
116 catch (Throwable t) {
117 throwHotDeployException(
118 hotDeployEvent, "Error registering portlets for ", t);
119 }
120 }
121
122 public void invokeUndeploy(HotDeployEvent hotDeployEvent)
123 throws HotDeployException {
124
125 try {
126 doInvokeUndeploy(hotDeployEvent);
127 }
128 catch (Throwable t) {
129 throwHotDeployException(
130 hotDeployEvent, "Error unregistering portlets for ", t);
131 }
132 }
133
134 protected void destroyPortlet(Portlet portlet, Set<String> portletIds)
135 throws Exception {
136
137 PortletApp portletApp = portlet.getPortletApp();
138
139 Set<PortletFilter> portletFilters = portletApp.getPortletFilters();
140
141 for (PortletFilter portletFilter : portletFilters) {
142 PortletFilterFactory.destroy(portletFilter);
143 }
144
145 Set<PortletURLListener> portletURLListeners =
146 portletApp.getPortletURLListeners();
147
148 for (PortletURLListener portletURLListener : portletURLListeners) {
149 PortletURLListenerFactory.destroy(portletURLListener);
150 }
151
152 List<Indexer> indexers = portlet.getIndexerInstances();
153
154 for (Indexer indexer : indexers) {
155 IndexerRegistryUtil.unregister(indexer);
156 }
157
158 if (PropsValues.SCHEDULER_ENABLED) {
159 List<SchedulerEntry> schedulerEntries =
160 portlet.getSchedulerEntries();
161
162 if ((schedulerEntries != null) && !schedulerEntries.isEmpty()) {
163 for (SchedulerEntry schedulerEntry : schedulerEntries) {
164 SchedulerEngineUtil.unschedule(
165 schedulerEntry, StorageType.MEMORY_CLUSTERED);
166 }
167 }
168 }
169
170 PollerProcessorUtil.deletePollerProcessor(portlet.getPortletId());
171
172 POPServerUtil.deleteListener(portlet.getPopMessageListenerInstance());
173
174 SocialActivityInterpreterLocalServiceUtil.deleteActivityInterpreter(
175 portlet.getSocialActivityInterpreterInstance());
176
177 SocialRequestInterpreterLocalServiceUtil.deleteRequestInterpreter(
178 portlet.getSocialRequestInterpreterInstance());
179
180 WebDAVUtil.deleteStorage(portlet.getWebDAVStorageInstance());
181
182 XmlRpcServlet.unregisterMethod(portlet.getXmlRpcMethodInstance());
183
184 List<AssetRendererFactory> assetRendererFactories =
185 portlet.getAssetRendererFactoryInstances();
186
187 if (assetRendererFactories != null) {
188 AssetRendererFactoryRegistryUtil.unregister(assetRendererFactories);
189 }
190
191 List<AtomCollectionAdapter<?>> atomCollectionAdapters =
192 portlet.getAtomCollectionAdapterInstances();
193
194 if (atomCollectionAdapters != null) {
195 AtomCollectionAdapterRegistryUtil.unregister(
196 atomCollectionAdapters);
197 }
198
199 List<WorkflowHandler> workflowHandlers =
200 portlet.getWorkflowHandlerInstances();
201
202 if (workflowHandlers != null) {
203 WorkflowHandlerRegistryUtil.unregister(workflowHandlers);
204 }
205
206 PortletInstanceFactoryUtil.destroy(portlet);
207
208 portletIds.add(portlet.getPortletId());
209 }
210
211 protected void doInvokeDeploy(HotDeployEvent hotDeployEvent)
212 throws Exception {
213
214
215
216 ServletContext servletContext = hotDeployEvent.getServletContext();
217
218 String servletContextName = servletContext.getServletContextName();
219
220 if (_log.isDebugEnabled()) {
221 _log.debug("Invoking deploy for " + servletContextName);
222 }
223
224
225
226 String configLocation = servletContext.getInitParameter(
227 PortletContextLoader.PORTAL_CONFIG_LOCATION_PARAM);
228
229 Properties serviceBuilderProperties =
230 (Properties)servletContext.getAttribute(
231 PluginPackageHotDeployListener.SERVICE_BUILDER_PROPERTIES);
232
233 if (Validator.isNotNull(configLocation) ||
234 (serviceBuilderProperties != null)) {
235
236 String lockKey = PortletContextLoaderListener.getLockKey(
237 servletContext);
238
239 Lock lock = LockRegistry.allocateLock(lockKey, lockKey);
240
241 lock.lock();
242 }
243
244
245
246 long[] companyIds = PortalInstances.getCompanyIds();
247
248
249
250 String[] xmls = new String[] {
251 HttpUtil.URLtoString(
252 servletContext.getResource(
253 "/WEB-INF/" + Portal.PORTLET_XML_FILE_NAME_STANDARD)),
254 HttpUtil.URLtoString(
255 servletContext.getResource(
256 "/WEB-INF/" + Portal.PORTLET_XML_FILE_NAME_CUSTOM)),
257 HttpUtil.URLtoString(
258 servletContext.getResource("/WEB-INF/liferay-portlet.xml")),
259 HttpUtil.URLtoString(servletContext.getResource("/WEB-INF/web.xml"))
260 };
261
262 if ((xmls[0] == null) && (xmls[1] == null)) {
263 return;
264 }
265
266 logRegistration(servletContextName);
267
268 List<Portlet> portlets = PortletLocalServiceUtil.initWAR(
269 servletContextName, servletContext, xmls,
270 hotDeployEvent.getPluginPackage());
271
272
273
274 ClassLoader portletClassLoader = hotDeployEvent.getContextClassLoader();
275
276 servletContext.setAttribute(
277 PortletServlet.PORTLET_CLASS_LOADER, portletClassLoader);
278
279
280
281 initLogger(portletClassLoader);
282
283
284
285 _portletAppInitialized = false;
286 _strutsBridges = false;
287
288 PortletBagFactory portletBagFactory = new PortletBagFactory();
289
290 portletBagFactory.setClassLoader(portletClassLoader);
291 portletBagFactory.setServletContext(servletContext);
292 portletBagFactory.setWARFile(true);
293
294 Iterator<Portlet> itr = portlets.iterator();
295
296 while (itr.hasNext()) {
297 Portlet portlet = itr.next();
298
299 PortletBag portletBag = initPortlet(portlet, portletBagFactory);
300
301 if (portletBag == null) {
302 itr.remove();
303 }
304 else {
305 if (!_portletAppInitialized) {
306 initPortletApp(
307 portlet, servletContextName, servletContext,
308 portletClassLoader);
309
310 _portletAppInitialized = true;
311 }
312 }
313 }
314
315
316
317 if (!_strutsBridges) {
318 _strutsBridges = GetterUtil.getBoolean(
319 servletContext.getInitParameter(
320 "struts-bridges-context-provider"));
321 }
322
323 if (_strutsBridges) {
324 servletContext.setAttribute(
325 ServletContextProvider.STRUTS_BRIDGES_CONTEXT_PROVIDER,
326 new LiferayServletContextProvider());
327 }
328
329
330
331 String xml = HttpUtil.URLtoString(
332 servletContext.getResource("/WEB-INF/liferay-display.xml"));
333
334 PortletCategory newPortletCategory =
335 PortletLocalServiceUtil.getWARDisplay(servletContextName, xml);
336
337 for (long companyId : companyIds) {
338 PortletCategory portletCategory = (PortletCategory)WebAppPool.get(
339 companyId, WebKeys.PORTLET_CATEGORY);
340
341 if (portletCategory != null) {
342 portletCategory.merge(newPortletCategory);
343 }
344 else {
345 _log.error(
346 "Unable to register portlet for company " + companyId +
347 " because it does not exist");
348 }
349 }
350
351
352
353 processPortletProperties(servletContextName, portletClassLoader);
354
355
356
357 itr = portlets.iterator();
358
359 while (itr.hasNext()) {
360 Portlet portlet = itr.next();
361
362 List<String> modelNames =
363 ResourceActionsUtil.getPortletModelResources(
364 portlet.getPortletId());
365
366 for (long companyId : companyIds) {
367 ResourceCodeLocalServiceUtil.checkResourceCodes(
368 companyId, portlet.getPortletId());
369
370 for (String modelName : modelNames) {
371 ResourceCodeLocalServiceUtil.checkResourceCodes(
372 companyId, modelName);
373 }
374 }
375
376 List<String> portletActions =
377 ResourceActionsUtil.getPortletResourceActions(
378 portlet.getPortletId());
379
380 ResourceActionLocalServiceUtil.checkResourceActions(
381 portlet.getPortletId(), portletActions);
382
383 for (String modelName : modelNames) {
384 List<String> modelActions =
385 ResourceActionsUtil.getModelResourceActions(modelName);
386
387 ResourceActionLocalServiceUtil.checkResourceActions(
388 modelName, modelActions);
389 }
390
391 for (long companyId : companyIds) {
392 Portlet curPortlet = PortletLocalServiceUtil.getPortletById(
393 companyId, portlet.getPortletId());
394
395 PortletLocalServiceUtil.checkPortlet(curPortlet);
396 }
397 }
398
399
400
401 for (Portlet portlet : portlets) {
402 boolean ready = GetterUtil.getBoolean(
403 servletContext.getInitParameter(
404 "portlets-ready-by-default"), true);
405
406 portlet.setReady(ready);
407 }
408
409
410
411 registerClpMessageListeners(servletContext, portletClassLoader);
412
413
414
415 DirectServletRegistry.clearServlets();
416 FileTimestampUtil.reset();
417
418
419
420 _vars.put(
421 servletContextName,
422 new ObjectValuePair<long[], List<Portlet>>(
423 companyIds, portlets));
424
425 if (_log.isInfoEnabled()) {
426 if (portlets.size() == 1) {
427 _log.info(
428 "1 portlet for " + servletContextName +
429 " is available for use");
430 }
431 else {
432 _log.info(
433 portlets.size() + " portlets for " + servletContextName +
434 " are available for use");
435 }
436 }
437 }
438
439 protected void doInvokeUndeploy(HotDeployEvent hotDeployEvent)
440 throws Exception {
441
442 ServletContext servletContext = hotDeployEvent.getServletContext();
443
444 String servletContextName = servletContext.getServletContextName();
445
446 if (_log.isDebugEnabled()) {
447 _log.debug("Invoking undeploy for " + servletContextName);
448 }
449
450 ObjectValuePair<long[], List<Portlet>> ovp =
451 _vars.remove(servletContextName);
452
453 if (ovp == null) {
454 return;
455 }
456
457 long[] companyIds = ovp.getKey();
458 List<Portlet> portlets = ovp.getValue();
459
460 Set<String> portletIds = new HashSet<String>();
461
462 if (portlets != null) {
463 if (_log.isInfoEnabled()) {
464 _log.info(
465 "Unregistering portlets for " + servletContextName);
466 }
467
468 Iterator<Portlet> itr = portlets.iterator();
469
470 while (itr.hasNext()) {
471 Portlet portlet = itr.next();
472
473 destroyPortlet(portlet, portletIds);
474 }
475 }
476
477 ServletContextPool.remove(servletContextName);
478
479 if (portletIds.size() > 0) {
480 for (long companyId : companyIds) {
481 PortletCategory portletCategory =
482 (PortletCategory)WebAppPool.get(
483 companyId, WebKeys.PORTLET_CATEGORY);
484
485 portletCategory.separate(portletIds);
486 }
487 }
488
489 PortletContextBagPool.remove(servletContextName);
490 PortletResourceBundles.remove(servletContextName);
491
492 unregisterClpMessageListeners(servletContext);
493
494 if (_log.isInfoEnabled()) {
495 if (portlets.size() == 1) {
496 _log.info(
497 "1 portlet for " + servletContextName +
498 " was unregistered");
499 }
500 else {
501 _log.info(
502 portlets.size() + " portlets for " + servletContextName +
503 " was unregistered");
504 }
505 }
506 }
507
508 protected void initLogger(ClassLoader portletClassLoader) {
509 Log4JUtil.configureLog4J(
510 portletClassLoader.getResource("META-INF/portal-log4j.xml"));
511 }
512
513 protected PortletBag initPortlet(
514 Portlet portlet, PortletBagFactory portletBagFactory)
515 throws Exception {
516
517 PortletBag portletBag = portletBagFactory.create(portlet);
518
519 if (portletBag == null) {
520 return null;
521 }
522
523 javax.portlet.Portlet portletInstance = portletBag.getPortletInstance();
524
525 if (ClassUtil.isSubclass(
526 portletInstance.getClass(), StrutsPortlet.class.getName())) {
527
528 _strutsBridges = true;
529 }
530
531 return portletBag;
532 }
533
534 protected void initPortletApp(
535 Portlet portlet, String servletContextName,
536 ServletContext servletContext, ClassLoader portletClassLoader)
537 throws Exception {
538
539 PortletContextBag portletContextBag = new PortletContextBag(
540 servletContextName);
541
542 PortletContextBagPool.put(servletContextName, portletContextBag);
543
544 PortletApp portletApp = portlet.getPortletApp();
545
546 servletContext.setAttribute(PortletServlet.PORTLET_APP, portletApp);
547
548 Map<String, String> customUserAttributes =
549 portletApp.getCustomUserAttributes();
550
551 for (Map.Entry<String, String> entry :
552 customUserAttributes.entrySet()) {
553
554 String attrCustomClass = entry.getValue();
555
556 CustomUserAttributes customUserAttributesInstance =
557 (CustomUserAttributes)portletClassLoader.loadClass(
558 attrCustomClass).newInstance();
559
560 portletContextBag.getCustomUserAttributes().put(
561 attrCustomClass, customUserAttributesInstance);
562 }
563
564 Set<PortletFilter> portletFilters = portletApp.getPortletFilters();
565
566 for (PortletFilter portletFilter : portletFilters) {
567 javax.portlet.filter.PortletFilter portletFilterInstance =
568 (javax.portlet.filter.PortletFilter)newInstance(
569 portletClassLoader,
570 new Class<?>[] {
571 javax.portlet.filter.ActionFilter.class,
572 javax.portlet.filter.EventFilter.class,
573 javax.portlet.filter.PortletFilter.class,
574 javax.portlet.filter.RenderFilter.class,
575 javax.portlet.filter.ResourceFilter.class
576 },
577 portletFilter.getFilterClass());
578
579 portletContextBag.getPortletFilters().put(
580 portletFilter.getFilterName(), portletFilterInstance);
581 }
582
583 InvokerPortlet invokerPortlet = PortletInstanceFactoryUtil.create(
584 portlet, servletContext);
585
586 invokerPortlet.setPortletFilters();
587
588 Set<PortletURLListener> portletURLListeners =
589 portletApp.getPortletURLListeners();
590
591 for (PortletURLListener portletURLListener : portletURLListeners) {
592 PortletURLGenerationListener portletURLListenerInstance =
593 (PortletURLGenerationListener)newInstance(
594 portletClassLoader, PortletURLGenerationListener.class,
595 portletURLListener.getListenerClass());
596
597 portletContextBag.getPortletURLListeners().put(
598 portletURLListener.getListenerClass(),
599 portletURLListenerInstance);
600
601 PortletURLListenerFactory.create(portletURLListener);
602 }
603 }
604
605 protected void logRegistration(String servletContextName) {
606 if (_log.isInfoEnabled()) {
607 _log.info("Registering portlets for " + servletContextName);
608 }
609 }
610
611 protected void processPortletProperties(
612 String servletContextName, ClassLoader portletClassLoader)
613 throws Exception {
614
615 Configuration portletPropertiesConfiguration = null;
616
617 try {
618 portletPropertiesConfiguration =
619 ConfigurationFactoryUtil.getConfiguration(
620 portletClassLoader, "portlet");
621 }
622 catch (Exception e) {
623 if (_log.isDebugEnabled()) {
624 _log.debug("Unable to read portlet.properties");
625 }
626
627 return;
628 }
629
630 Properties portletProperties =
631 portletPropertiesConfiguration.getProperties();
632
633 if (portletProperties.size() == 0) {
634 return;
635 }
636
637 String languageBundleName = portletProperties.getProperty(
638 "language.bundle");
639
640 if (Validator.isNotNull(languageBundleName)) {
641 Locale[] locales = LanguageUtil.getAvailableLocales();
642
643 for (Locale locale : locales) {
644 ResourceBundle resourceBundle = ResourceBundle.getBundle(
645 languageBundleName, locale, portletClassLoader);
646
647 PortletResourceBundles.put(
648 servletContextName, LocaleUtil.toLanguageId(locale),
649 resourceBundle);
650 }
651 }
652
653 String[] resourceActionConfigs = StringUtil.split(
654 portletProperties.getProperty(PropsKeys.RESOURCE_ACTIONS_CONFIGS));
655
656 for (String resourceActionConfig : resourceActionConfigs) {
657 ResourceActionsUtil.read(
658 servletContextName, portletClassLoader, resourceActionConfig);
659 }
660 }
661
662 private static Log _log = LogFactoryUtil.getLog(
663 PortletHotDeployListener.class);
664
665 private static Map<String, ObjectValuePair<long[], List<Portlet>>> _vars =
666 new HashMap<String, ObjectValuePair<long[], List<Portlet>>>();
667
668 private boolean _portletAppInitialized;
669 private boolean _strutsBridges;
670
671 }