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