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>>(companyIds, portlets));
423
424 if (_log.isInfoEnabled()) {
425 if (portlets.size() == 1) {
426 _log.info(
427 "1 portlet for " + servletContextName +
428 " is available for use");
429 }
430 else {
431 _log.info(
432 portlets.size() + " portlets for " + servletContextName +
433 " are available for use");
434 }
435 }
436 }
437
438 protected void doInvokeUndeploy(HotDeployEvent hotDeployEvent)
439 throws Exception {
440
441 ServletContext servletContext = hotDeployEvent.getServletContext();
442
443 String servletContextName = servletContext.getServletContextName();
444
445 if (_log.isDebugEnabled()) {
446 _log.debug("Invoking undeploy for " + servletContextName);
447 }
448
449 ObjectValuePair<long[], List<Portlet>> ovp =
450 _vars.remove(servletContextName);
451
452 if (ovp == null) {
453 return;
454 }
455
456 long[] companyIds = ovp.getKey();
457 List<Portlet> portlets = ovp.getValue();
458
459 Set<String> portletIds = new HashSet<String>();
460
461 if (portlets != null) {
462 if (_log.isInfoEnabled()) {
463 _log.info("Unregistering portlets for " + servletContextName);
464 }
465
466 Iterator<Portlet> itr = portlets.iterator();
467
468 while (itr.hasNext()) {
469 Portlet portlet = itr.next();
470
471 destroyPortlet(portlet, portletIds);
472 }
473 }
474
475 ServletContextPool.remove(servletContextName);
476
477 if (portletIds.size() > 0) {
478 for (long companyId : companyIds) {
479 PortletCategory portletCategory =
480 (PortletCategory)WebAppPool.get(
481 companyId, WebKeys.PORTLET_CATEGORY);
482
483 portletCategory.separate(portletIds);
484 }
485 }
486
487 PortletContextBagPool.remove(servletContextName);
488 PortletResourceBundles.remove(servletContextName);
489
490 unregisterClpMessageListeners(servletContext);
491
492 if (_log.isInfoEnabled()) {
493 if (portlets.size() == 1) {
494 _log.info(
495 "1 portlet for " + servletContextName +
496 " was unregistered");
497 }
498 else {
499 _log.info(
500 portlets.size() + " portlets for " + servletContextName +
501 " was unregistered");
502 }
503 }
504 }
505
506 protected void initLogger(ClassLoader portletClassLoader) {
507 Log4JUtil.configureLog4J(
508 portletClassLoader.getResource("META-INF/portal-log4j.xml"));
509 }
510
511 protected PortletBag initPortlet(
512 Portlet portlet, PortletBagFactory portletBagFactory)
513 throws Exception {
514
515 PortletBag portletBag = portletBagFactory.create(portlet);
516
517 if (portletBag == null) {
518 return null;
519 }
520
521 javax.portlet.Portlet portletInstance = portletBag.getPortletInstance();
522
523 if (ClassUtil.isSubclass(
524 portletInstance.getClass(), StrutsPortlet.class.getName())) {
525
526 _strutsBridges = true;
527 }
528
529 return portletBag;
530 }
531
532 protected void initPortletApp(
533 Portlet portlet, String servletContextName,
534 ServletContext servletContext, ClassLoader portletClassLoader)
535 throws Exception {
536
537 PortletContextBag portletContextBag = new PortletContextBag(
538 servletContextName);
539
540 PortletContextBagPool.put(servletContextName, portletContextBag);
541
542 PortletApp portletApp = portlet.getPortletApp();
543
544 servletContext.setAttribute(PortletServlet.PORTLET_APP, portletApp);
545
546 Map<String, String> customUserAttributes =
547 portletApp.getCustomUserAttributes();
548
549 for (Map.Entry<String, String> entry :
550 customUserAttributes.entrySet()) {
551
552 String attrCustomClass = entry.getValue();
553
554 CustomUserAttributes customUserAttributesInstance =
555 (CustomUserAttributes)portletClassLoader.loadClass(
556 attrCustomClass).newInstance();
557
558 portletContextBag.getCustomUserAttributes().put(
559 attrCustomClass, customUserAttributesInstance);
560 }
561
562 Set<PortletFilter> portletFilters = portletApp.getPortletFilters();
563
564 for (PortletFilter portletFilter : portletFilters) {
565 javax.portlet.filter.PortletFilter portletFilterInstance =
566 (javax.portlet.filter.PortletFilter)newInstance(
567 portletClassLoader,
568 new Class<?>[] {
569 javax.portlet.filter.ActionFilter.class,
570 javax.portlet.filter.EventFilter.class,
571 javax.portlet.filter.PortletFilter.class,
572 javax.portlet.filter.RenderFilter.class,
573 javax.portlet.filter.ResourceFilter.class
574 },
575 portletFilter.getFilterClass());
576
577 portletContextBag.getPortletFilters().put(
578 portletFilter.getFilterName(), portletFilterInstance);
579 }
580
581 InvokerPortlet invokerPortlet = PortletInstanceFactoryUtil.create(
582 portlet, servletContext);
583
584 invokerPortlet.setPortletFilters();
585
586 Set<PortletURLListener> portletURLListeners =
587 portletApp.getPortletURLListeners();
588
589 for (PortletURLListener portletURLListener : portletURLListeners) {
590 PortletURLGenerationListener portletURLListenerInstance =
591 (PortletURLGenerationListener)newInstance(
592 portletClassLoader, PortletURLGenerationListener.class,
593 portletURLListener.getListenerClass());
594
595 portletContextBag.getPortletURLListeners().put(
596 portletURLListener.getListenerClass(),
597 portletURLListenerInstance);
598
599 PortletURLListenerFactory.create(portletURLListener);
600 }
601 }
602
603 protected void logRegistration(String servletContextName) {
604 if (_log.isInfoEnabled()) {
605 _log.info("Registering portlets for " + servletContextName);
606 }
607 }
608
609 protected void processPortletProperties(
610 String servletContextName, ClassLoader portletClassLoader)
611 throws Exception {
612
613 Configuration portletPropertiesConfiguration = null;
614
615 try {
616 portletPropertiesConfiguration =
617 ConfigurationFactoryUtil.getConfiguration(
618 portletClassLoader, "portlet");
619 }
620 catch (Exception e) {
621 if (_log.isDebugEnabled()) {
622 _log.debug("Unable to read portlet.properties");
623 }
624
625 return;
626 }
627
628 Properties portletProperties =
629 portletPropertiesConfiguration.getProperties();
630
631 if (portletProperties.size() == 0) {
632 return;
633 }
634
635 String languageBundleName = portletProperties.getProperty(
636 "language.bundle");
637
638 if (Validator.isNotNull(languageBundleName)) {
639 Locale[] locales = LanguageUtil.getAvailableLocales();
640
641 for (Locale locale : locales) {
642 ResourceBundle resourceBundle = ResourceBundle.getBundle(
643 languageBundleName, locale, portletClassLoader);
644
645 PortletResourceBundles.put(
646 servletContextName, LocaleUtil.toLanguageId(locale),
647 resourceBundle);
648 }
649 }
650
651 String[] resourceActionConfigs = StringUtil.split(
652 portletProperties.getProperty(PropsKeys.RESOURCE_ACTIONS_CONFIGS));
653
654 for (String resourceActionConfig : resourceActionConfigs) {
655 ResourceActionsUtil.read(
656 servletContextName, portletClassLoader, resourceActionConfig);
657 }
658 }
659
660 private static Log _log = LogFactoryUtil.getLog(
661 PortletHotDeployListener.class);
662
663 private static Map<String, ObjectValuePair<long[], List<Portlet>>> _vars =
664 new HashMap<String, ObjectValuePair<long[], List<Portlet>>>();
665
666 private boolean _portletAppInitialized;
667 private boolean _strutsBridges;
668
669 }