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 registerClpMessageListeners(servletContext, portletClassLoader);
359
360
361
362 _vars.put(
363 servletContextName,
364 new ObjectValuePair<long[], List<Portlet>>(
365 companyIds, portlets));
366
367 if (_log.isInfoEnabled()) {
368 if (portlets.size() == 1) {
369 _log.info(
370 "1 portlet for " + servletContextName +
371 " is available for use");
372 }
373 else {
374 _log.info(
375 portlets.size() + " portlets for " + servletContextName +
376 " are available for use");
377 }
378 }
379 }
380
381 protected void doInvokeUndeploy(HotDeployEvent event) throws Exception {
382 ServletContext servletContext = event.getServletContext();
383
384 String servletContextName = servletContext.getServletContextName();
385
386 if (_log.isDebugEnabled()) {
387 _log.debug("Invoking undeploy for " + servletContextName);
388 }
389
390 ObjectValuePair<long[], List<Portlet>> ovp =
391 _vars.remove(servletContextName);
392
393 if (ovp == null) {
394 return;
395 }
396
397 long[] companyIds = ovp.getKey();
398 List<Portlet> portlets = ovp.getValue();
399
400 Set<String> portletIds = new HashSet<String>();
401
402 if (portlets != null) {
403 if (_log.isInfoEnabled()) {
404 _log.info(
405 "Unregistering portlets for " + servletContextName);
406 }
407
408 Iterator<Portlet> itr = portlets.iterator();
409
410 while (itr.hasNext()) {
411 Portlet portlet = itr.next();
412
413 destroyPortlet(portlet, portletIds);
414 }
415 }
416
417 if (portletIds.size() > 0) {
418 for (int i = 0; i < companyIds.length; i++) {
419 long companyId = companyIds[i];
420
421 PortletCategory portletCategory =
422 (PortletCategory)WebAppPool.get(
423 String.valueOf(companyId), WebKeys.PORTLET_CATEGORY);
424
425 portletCategory.separate(portletIds);
426 }
427 }
428
429 PortletResourceBundles.remove(servletContextName);
430
431 unregisterClpMessageListeners(servletContext);
432
433 if (_log.isInfoEnabled()) {
434 if (portlets.size() == 1) {
435 _log.info(
436 "1 portlet for " + servletContextName +
437 " was unregistered");
438 }
439 else {
440 _log.info(
441 portlets.size() + " portlets for " + servletContextName +
442 " was unregistered");
443 }
444 }
445 }
446
447 protected void initLogger(ClassLoader portletClassLoader) {
448 Log4JUtil.configureLog4J(
449 portletClassLoader.getResource("META-INF/portal-log4j.xml"));
450 }
451
452 protected PortletBag initPortlet(
453 Portlet portlet, PortletBagFactory portletBagFactory)
454 throws Exception {
455
456 PortletBag portletBag = portletBagFactory.create(portlet);
457
458 if (portletBag == null) {
459 return null;
460 }
461
462 javax.portlet.Portlet portletInstance = portletBag.getPortletInstance();
463
464 if (ClassUtil.isSubclass(
465 portletInstance.getClass(), StrutsPortlet.class.getName())) {
466
467 _strutsBridges = true;
468 }
469
470 return portletBag;
471 }
472
473 protected void initPortletApp(
474 Portlet portlet, String servletContextName,
475 ServletContext servletContext, ClassLoader portletClassLoader)
476 throws Exception {
477
478 PortletContextBag portletContextBag = new PortletContextBag(
479 servletContextName);
480
481 PortletContextBagPool.put(servletContextName, portletContextBag);
482
483 PortletApp portletApp = portlet.getPortletApp();
484
485 servletContext.setAttribute(PortletServlet.PORTLET_APP, portletApp);
486
487 Map<String, String> customUserAttributes =
488 portletApp.getCustomUserAttributes();
489
490 for (Map.Entry<String, String> entry :
491 customUserAttributes.entrySet()) {
492
493 String attrCustomClass = entry.getValue();
494
495 CustomUserAttributes customUserAttributesInstance =
496 (CustomUserAttributes)portletClassLoader.loadClass(
497 attrCustomClass).newInstance();
498
499 portletContextBag.getCustomUserAttributes().put(
500 attrCustomClass, customUserAttributesInstance);
501 }
502
503 Set<PortletFilter> portletFilters = portletApp.getPortletFilters();
504
505 for (PortletFilter portletFilter : portletFilters) {
506 javax.portlet.filter.PortletFilter portletFilterInstance =
507 (javax.portlet.filter.PortletFilter)newInstance(
508 portletClassLoader,
509 new Class<?>[] {
510 javax.portlet.filter.ActionFilter.class,
511 javax.portlet.filter.EventFilter.class,
512 javax.portlet.filter.PortletFilter.class,
513 javax.portlet.filter.RenderFilter.class,
514 javax.portlet.filter.ResourceFilter.class
515 },
516 portletFilter.getFilterClass());
517
518 portletContextBag.getPortletFilters().put(
519 portletFilter.getFilterName(), portletFilterInstance);
520 }
521
522 InvokerPortlet invokerPortlet = PortletInstanceFactoryUtil.create(
523 portlet, servletContext);
524
525 invokerPortlet.setPortletFilters();
526
527 Set<PortletURLListener> portletURLListeners =
528 portletApp.getPortletURLListeners();
529
530 for (PortletURLListener portletURLListener : portletURLListeners) {
531 PortletURLGenerationListener portletURLListenerInstance =
532 (PortletURLGenerationListener)newInstance(
533 portletClassLoader, PortletURLGenerationListener.class,
534 portletURLListener.getListenerClass());
535
536 portletContextBag.getPortletURLListeners().put(
537 portletURLListener.getListenerClass(),
538 portletURLListenerInstance);
539
540 PortletURLListenerFactory.create(portletURLListener);
541 }
542 }
543
544 protected void processPortletProperties(
545 String servletContextName, ClassLoader portletClassLoader)
546 throws Exception {
547
548 Configuration portletPropertiesConfiguration = null;
549
550 try {
551 portletPropertiesConfiguration =
552 ConfigurationFactoryUtil.getConfiguration(
553 portletClassLoader, "portlet");
554 }
555 catch (Exception e) {
556 if (_log.isDebugEnabled()) {
557 _log.debug("Unable to read portlet.properties");
558 }
559
560 return;
561 }
562
563 Properties portletProperties =
564 portletPropertiesConfiguration.getProperties();
565
566 if (portletProperties.size() == 0) {
567 return;
568 }
569
570 String languageBundleName = portletProperties.getProperty(
571 "language.bundle");
572
573 if (Validator.isNotNull(languageBundleName)) {
574 Locale[] locales = LanguageUtil.getAvailableLocales();
575
576 for (int i = 0; i < locales.length; i++) {
577 ResourceBundle resourceBundle = ResourceBundle.getBundle(
578 languageBundleName, locales[i], portletClassLoader);
579
580 PortletResourceBundles.put(
581 servletContextName, LocaleUtil.toLanguageId(locales[i]),
582 resourceBundle);
583 }
584 }
585
586 String[] resourceActionConfigs = StringUtil.split(
587 portletProperties.getProperty("resource.actions.configs"));
588
589 for (int i = 0; i < resourceActionConfigs.length; i++) {
590 ResourceActionsUtil.read(
591 servletContextName, portletClassLoader,
592 resourceActionConfigs[i]);
593 }
594 }
595
596 private static Log _log = LogFactoryUtil.getLog(
597 PortletHotDeployListener.class);
598
599 private static Map<String, ObjectValuePair<long[], List<Portlet>>> _vars =
600 new HashMap<String, ObjectValuePair<long[], List<Portlet>>>();
601
602 private boolean _portletAppInitialized;
603 private boolean _strutsBridges;
604
605 }