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