1
22
23 package com.liferay.portal.deploy.hot;
24
25 import com.liferay.portal.apache.bridges.struts.LiferayServletContextProvider;
26 import com.liferay.portal.job.Scheduler;
27 import com.liferay.portal.kernel.deploy.hot.HotDeployEvent;
28 import com.liferay.portal.kernel.deploy.hot.HotDeployException;
29 import com.liferay.portal.kernel.deploy.hot.HotDeployListener;
30 import com.liferay.portal.kernel.language.LanguageUtil;
31 import com.liferay.portal.kernel.lar.PortletDataHandler;
32 import com.liferay.portal.kernel.pop.MessageListener;
33 import com.liferay.portal.kernel.portlet.ConfigurationAction;
34 import com.liferay.portal.kernel.portlet.FriendlyURLMapper;
35 import com.liferay.portal.kernel.portlet.PortletLayoutListener;
36 import com.liferay.portal.kernel.search.Indexer;
37 import com.liferay.portal.kernel.servlet.PortletServlet;
38 import com.liferay.portal.kernel.servlet.ServletContextProvider;
39 import com.liferay.portal.kernel.servlet.URLEncoder;
40 import com.liferay.portal.kernel.util.ClassUtil;
41 import com.liferay.portal.kernel.util.GetterUtil;
42 import com.liferay.portal.kernel.util.LocaleUtil;
43 import com.liferay.portal.kernel.util.ObjectValuePair;
44 import com.liferay.portal.kernel.util.PropertiesUtil;
45 import com.liferay.portal.kernel.util.StringUtil;
46 import com.liferay.portal.kernel.util.Validator;
47 import com.liferay.portal.model.ActivityTrackerInterpreter;
48 import com.liferay.portal.model.Portlet;
49 import com.liferay.portal.model.PortletCategory;
50 import com.liferay.portal.model.impl.ActivityTrackerInterpreterImpl;
51 import com.liferay.portal.pop.POPServerUtil;
52 import com.liferay.portal.security.permission.ResourceActionsUtil;
53 import com.liferay.portal.service.PortletLocalServiceUtil;
54 import com.liferay.portal.service.ServiceComponentLocalServiceUtil;
55 import com.liferay.portal.servlet.PortletContextPool;
56 import com.liferay.portal.servlet.PortletContextWrapper;
57 import com.liferay.portal.util.ActivityTrackerInterpreterUtil;
58 import com.liferay.portal.util.PortalInstances;
59 import com.liferay.portal.util.PortalUtil;
60 import com.liferay.portal.util.PropsValues;
61 import com.liferay.portal.util.WebAppPool;
62 import com.liferay.portal.util.WebKeys;
63 import com.liferay.portlet.PortletInstanceFactory;
64 import com.liferay.portlet.PortletPreferencesSerializer;
65 import com.liferay.portlet.PortletResourceBundles;
66 import com.liferay.util.CollectionFactory;
67 import com.liferay.util.Http;
68
69 import java.util.HashSet;
70 import java.util.Iterator;
71 import java.util.List;
72 import java.util.Locale;
73 import java.util.Map;
74 import java.util.MissingResourceException;
75 import java.util.Properties;
76 import java.util.ResourceBundle;
77 import java.util.Set;
78
79 import javax.portlet.PreferencesValidator;
80
81 import javax.servlet.ServletContext;
82
83 import org.apache.commons.logging.Log;
84 import org.apache.commons.logging.LogFactory;
85 import org.apache.portals.bridges.struts.StrutsPortlet;
86
87
95 public class PortletHotDeployListener implements HotDeployListener {
96
97 public void invokeDeploy(HotDeployEvent event) throws HotDeployException {
98 String servletContextName = null;
99
100 try {
101
102
104 ServletContext ctx = event.getServletContext();
105
106 servletContextName = ctx.getServletContextName();
107
108 if (_log.isDebugEnabled()) {
109 _log.debug("Invoking deploy for " + servletContextName);
110 }
111
112
114 long[] companyIds = PortalInstances.getCompanyIds();
115
116
118 String[] xmls = new String[] {
119 Http.URLtoString(ctx.getResource(
120 "/WEB-INF/" + PortalUtil.PORTLET_XML_FILE_NAME_STANDARD)),
121 Http.URLtoString(ctx.getResource(
122 "/WEB-INF/" + PortalUtil.PORTLET_XML_FILE_NAME_CUSTOM)),
123 Http.URLtoString(ctx.getResource(
124 "/WEB-INF/liferay-portlet.xml")),
125 Http.URLtoString(ctx.getResource("/WEB-INF/web.xml"))
126 };
127
128 if (xmls[0] == null) {
129 return;
130 }
131
132 if (_log.isInfoEnabled()) {
133 _log.info("Registering portlets for " + servletContextName);
134 }
135
136 List portlets = PortletLocalServiceUtil.initWAR(
137 servletContextName, xmls, event.getPluginPackage());
138
139
141 ClassLoader portletClassLoader = event.getContextClassLoader();
142
143 ctx.setAttribute(
144 PortletServlet.PORTLET_CLASS_LOADER, portletClassLoader);
145
146
148 boolean strutsBridges = false;
149
150 Iterator itr1 = portlets.iterator();
151
152 while (itr1.hasNext()) {
153 Portlet portlet = (Portlet)itr1.next();
154
155 Class portletClass = portletClassLoader.loadClass(
156 portlet.getPortletClass());
157
158 javax.portlet.Portlet portletInstance =
159 (javax.portlet.Portlet)portletClass.newInstance();
160
161 if (ClassUtil.isSubclass(portletClass,
162 StrutsPortlet.class.getName())) {
163
164 strutsBridges = true;
165 }
166
167 ConfigurationAction configurationActionInstance = null;
168
169 if (Validator.isNotNull(
170 portlet.getConfigurationActionClass())) {
171
172 configurationActionInstance =
173 (ConfigurationAction)portletClassLoader.loadClass(
174 portlet.getConfigurationActionClass()).
175 newInstance();
176 }
177
178 Indexer indexerInstance = null;
179
180 if (Validator.isNotNull(portlet.getIndexerClass())) {
181 indexerInstance = (Indexer)portletClassLoader.loadClass(
182 portlet.getIndexerClass()).newInstance();
183 }
184
185 Scheduler schedulerInstance = null;
186
187 if (Validator.isNotNull(portlet.getSchedulerClass())) {
188 schedulerInstance = (Scheduler)portletClassLoader.loadClass(
189 portlet.getSchedulerClass()).newInstance();
190 }
191
192 FriendlyURLMapper friendlyURLMapperInstance = null;
193
194 if (Validator.isNotNull(portlet.getFriendlyURLMapperClass())) {
195 friendlyURLMapperInstance =
196 (FriendlyURLMapper)portletClassLoader.loadClass(
197 portlet.getFriendlyURLMapperClass()).newInstance();
198 }
199
200 URLEncoder urlEncoderInstance = null;
201
202 if (Validator.isNotNull(portlet.getURLEncoderClass())) {
203 urlEncoderInstance =
204 (URLEncoder)portletClassLoader.loadClass(
205 portlet.getURLEncoderClass()).newInstance();
206 }
207
208 PortletDataHandler portletDataHandlerInstance = null;
209
210 if (Validator.isNotNull(portlet.getPortletDataHandlerClass())) {
211 portletDataHandlerInstance =
212 (PortletDataHandler)portletClassLoader.loadClass(
213 portlet.getPortletDataHandlerClass()).newInstance();
214 }
215
216 PortletLayoutListener portletLayoutListenerInstance = null;
217
218 if (Validator.isNotNull(
219 portlet.getPortletLayoutListenerClass())) {
220
221 portletLayoutListenerInstance =
222 (PortletLayoutListener)portletClassLoader.loadClass(
223 portlet.getPortletLayoutListenerClass()).
224 newInstance();
225 }
226
227 ActivityTrackerInterpreter activityTrackerInterpreterInstance =
228 null;
229
230 if (Validator.isNotNull(
231 portlet.getActivityTrackerInterpreterClass())) {
232
233 activityTrackerInterpreterInstance =
234 (ActivityTrackerInterpreter)
235 portletClassLoader.loadClass(
236 portlet.getActivityTrackerInterpreterClass()).
237 newInstance();
238
239 activityTrackerInterpreterInstance =
240 new ActivityTrackerInterpreterImpl(
241 activityTrackerInterpreterInstance);
242
243 ActivityTrackerInterpreterUtil.
244 addActivityTrackerInterpreter(
245 activityTrackerInterpreterInstance);
246 }
247
248 MessageListener popMessageListenerInstance = null;
249
250 if (Validator.isNotNull(
251 portlet.getPopMessageListenerClass())) {
252
253 popMessageListenerInstance =
254 (MessageListener)portletClassLoader.loadClass(
255 portlet.getPopMessageListenerClass()).
256 newInstance();
257
258 POPServerUtil.addListener(popMessageListenerInstance);
259 }
260
261 PreferencesValidator prefsValidatorInstance = null;
262
263 if (Validator.isNotNull(portlet.getPreferencesValidator())) {
264 prefsValidatorInstance =
265 (PreferencesValidator)portletClassLoader.loadClass(
266 portlet.getPreferencesValidator()).newInstance();
267
268 try {
269 if (PropsValues.PREFERENCE_VALIDATE_ON_STARTUP) {
270 prefsValidatorInstance.validate(
271 PortletPreferencesSerializer.fromDefaultXML(
272 portlet.getDefaultPreferences()));
273 }
274 }
275 catch (Exception e1) {
276 _log.warn(
277 "Portlet with the name " + portlet.getPortletId() +
278 " does not have valid default preferences");
279 }
280 }
281
282 Map resourceBundles = null;
283
284 if (Validator.isNotNull(portlet.getResourceBundle())) {
285 resourceBundles = CollectionFactory.getHashMap();
286
287 Iterator itr2 = portlet.getSupportedLocales().iterator();
288
289 while (itr2.hasNext()) {
290 String supportedLocale = (String)itr2.next();
291
292 Locale locale = LocaleUtil.fromLanguageId(
293 supportedLocale);
294
295 try {
296 ResourceBundle resourceBundle =
297 ResourceBundle.getBundle(
298 portlet.getResourceBundle(), locale,
299 portletClassLoader);
300
301 resourceBundles.put(
302 LocaleUtil.toLanguageId(locale),
303 resourceBundle);
304 }
305 catch (MissingResourceException mre) {
306 _log.warn(mre.getMessage());
307 }
308 }
309 }
310
311 Map customUserAttributes = CollectionFactory.getHashMap();
312
313 Iterator itr2 =
314 portlet.getCustomUserAttributes().entrySet().iterator();
315
316 while (itr2.hasNext()) {
317 Map.Entry entry = (Map.Entry)itr2.next();
318
319 String attrCustomClass = (String)entry.getValue();
320
321 customUserAttributes.put(
322 attrCustomClass,
323 portletClassLoader.loadClass(
324 attrCustomClass).newInstance());
325 }
326
327 PortletContextWrapper pcw = new PortletContextWrapper(
328 portlet.getPortletId(), ctx, portletInstance,
329 configurationActionInstance, indexerInstance,
330 schedulerInstance, friendlyURLMapperInstance,
331 urlEncoderInstance, portletDataHandlerInstance,
332 portletLayoutListenerInstance,
333 activityTrackerInterpreterInstance,
334 popMessageListenerInstance, prefsValidatorInstance,
335 resourceBundles, customUserAttributes);
336
337 PortletContextPool.put(portlet.getPortletId(), pcw);
338
339 try {
340 PortletInstanceFactory.create(portlet, ctx);
341 }
342 catch (Exception e1) {
343 if (_log.isWarnEnabled()) {
344 _log.warn(e1.getMessage());
345 }
346 }
347 }
348
349
351 if (!strutsBridges) {
352 strutsBridges = GetterUtil.getBoolean(
353 ctx.getInitParameter("struts-bridges-context-provider"));
354 }
355
356 if (strutsBridges) {
357 ctx.setAttribute(
358 ServletContextProvider.STRUTS_BRIDGES_CONTEXT_PROVIDER,
359 new LiferayServletContextProvider());
360 }
361
362
364 String xml = Http.URLtoString(ctx.getResource(
365 "/WEB-INF/liferay-display.xml"));
366
367 PortletCategory newPortletCategory =
368 PortletLocalServiceUtil.getWARDisplay(servletContextName, xml);
369
370 for (int i = 0; i < companyIds.length; i++) {
371 long companyId = companyIds[i];
372
373 PortletCategory portletCategory =
374 (PortletCategory)WebAppPool.get(
375 String.valueOf(companyId), WebKeys.PORTLET_CATEGORY);
376
377 if (portletCategory != null) {
378 portletCategory.merge(newPortletCategory);
379 }
380 else {
381 _log.error(
382 "Unable to register portlet for company " + companyId +
383 " because it does not exist");
384 }
385 }
386
387
389 String portletPropsName = ctx.getInitParameter(
390 "portlet_properties");
391
392 if (Validator.isNotNull(portletPropsName)) {
393 if (_log.isDebugEnabled()) {
394 _log.debug(
395 "Loading portlet properties " + portletPropsName);
396 }
397
398 Properties portletProps = new Properties();
399
400 PropertiesUtil.load(
401 portletProps,
402 StringUtil.read(portletClassLoader, portletPropsName));
403
404 if (_log.isDebugEnabled()) {
405 String portletPropsString = PropertiesUtil.list(
406 portletProps);
407
408 _log.debug(portletPropsString);
409 }
410
411 processProperties(
412 servletContextName, portletClassLoader, portletProps);
413 }
414
415
417 processServiceBuilder(ctx, portletClassLoader);
418
419
421 _vars.put(
422 servletContextName, new ObjectValuePair(companyIds, portlets));
423
424 if (_log.isInfoEnabled()) {
425 _log.info(
426 "Portlets for " + servletContextName +
427 " registered successfully");
428 }
429 }
430 catch (Exception e2) {
431 throw new HotDeployException(
432 "Error registering portlets for " + servletContextName, e2);
433 }
434 }
435
436 public void invokeUndeploy(HotDeployEvent event) throws HotDeployException {
437 String servletContextName = null;
438
439 try {
440 ServletContext ctx = event.getServletContext();
441
442 servletContextName = ctx.getServletContextName();
443
444 if (_log.isDebugEnabled()) {
445 _log.debug("Invoking undeploy for " + servletContextName);
446 }
447
448 ObjectValuePair ovp = (ObjectValuePair)_vars.remove(
449 servletContextName);
450
451 if (ovp == null) {
452 return;
453 }
454
455 long[] companyIds = (long[])ovp.getKey();
456 List portlets = (List)ovp.getValue();
457
458 Set portletIds = new HashSet();
459
460 if (portlets != null) {
461 if (_log.isInfoEnabled()) {
462 _log.info(
463 "Unregistering portlets for " + servletContextName);
464 }
465
466 Iterator itr = portlets.iterator();
467
468 while (itr.hasNext()) {
469 Portlet portlet = (Portlet)itr.next();
470
471 ActivityTrackerInterpreterUtil.
472 deleteActivityTrackerInterpreter(
473 portlet.getActivityTrackerInterpreterInstance());
474
475 POPServerUtil.deleteListener(
476 portlet.getPopMessageListenerInstance());
477
478 PortletInstanceFactory.destroy(portlet);
479
480 portletIds.add(portlet.getPortletId());
481 }
482 }
483
484 if (portletIds.size() > 0) {
485 for (int i = 0; i < companyIds.length; i++) {
486 long companyId = companyIds[i];
487
488 PortletCategory portletCategory =
489 (PortletCategory)WebAppPool.get(
490 String.valueOf(companyId),
491 WebKeys.PORTLET_CATEGORY);
492
493 portletCategory.separate(portletIds);
494 }
495 }
496
497 PortletResourceBundles.remove(servletContextName);
498
499 if (_log.isInfoEnabled()) {
500 _log.info(
501 "Portlets for " + servletContextName +
502 " unregistered successfully");
503 }
504 }
505 catch (Exception e) {
506 throw new HotDeployException(
507 "Error unregistering portlets for " + servletContextName, e);
508 }
509 }
510
511 protected void processProperties(
512 String servletContextName, ClassLoader portletClassLoader,
513 Properties portletProps)
514 throws Exception {
515
516 String languageBundleName = portletProps.getProperty("language.bundle");
517
518 if (Validator.isNotNull(languageBundleName)) {
519 Locale[] locales = LanguageUtil.getAvailableLocales();
520
521 for (int i = 0; i < locales.length; i++) {
522 ResourceBundle bundle = ResourceBundle.getBundle(
523 languageBundleName, locales[i], portletClassLoader);
524
525 PortletResourceBundles.put(
526 servletContextName, LocaleUtil.toLanguageId(locales[i]),
527 bundle);
528 }
529 }
530
531 String[] resourceActionConfigs = StringUtil.split(
532 portletProps.getProperty("resource.actions.configs"));
533
534 for (int i = 0; i < resourceActionConfigs.length; i++) {
535 ResourceActionsUtil.read(
536 servletContextName, portletClassLoader,
537 resourceActionConfigs[i]);
538 }
539 }
540
541 protected void processServiceBuilder(
542 ServletContext ctx, ClassLoader portletClassLoader)
543 throws Exception {
544
545 if (portletClassLoader.getResourceAsStream(
546 "portlet-service.properties") == null) {
547
548 return;
549 }
550
551 Properties serviceBuilderProps = new Properties();
552
553 PropertiesUtil.load(
554 serviceBuilderProps,
555 StringUtil.read(portletClassLoader, "portlet-service.properties"));
556
557 String buildNamespace = GetterUtil.getString(
558 serviceBuilderProps.getProperty("build.namespace"));
559 long buildNumber = GetterUtil.getLong(
560 serviceBuilderProps.getProperty("build.number"));
561 long buildDate = GetterUtil.getLong(
562 serviceBuilderProps.getProperty("build.date"));
563
564 if (_log.isDebugEnabled()) {
565 _log.debug("Build namespace " + buildNamespace);
566 _log.debug("Build number " + buildNumber);
567 _log.debug("Build date " + buildDate);
568 }
569
570 ServiceComponentLocalServiceUtil.updateServiceComponent(
571 ctx, portletClassLoader, buildNamespace, buildNumber, buildDate);
572 }
573
574 private static Log _log = LogFactory.getLog(PortletHotDeployListener.class);
575
576 private static Map _vars = CollectionFactory.getHashMap();
577
578 }