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