1
22
23 package com.liferay.portal.deploy.hot;
24
25 import com.liferay.portal.events.EventsProcessorUtil;
26 import com.liferay.portal.kernel.bean.ContextClassLoaderBeanHandler;
27 import com.liferay.portal.kernel.bean.PortalBeanLocatorUtil;
28 import com.liferay.portal.kernel.configuration.Configuration;
29 import com.liferay.portal.kernel.configuration.ConfigurationFactoryUtil;
30 import com.liferay.portal.kernel.deploy.hot.HotDeployEvent;
31 import com.liferay.portal.kernel.deploy.hot.HotDeployException;
32 import com.liferay.portal.kernel.events.Action;
33 import com.liferay.portal.kernel.events.InvokerAction;
34 import com.liferay.portal.kernel.events.InvokerSessionAction;
35 import com.liferay.portal.kernel.events.InvokerSimpleAction;
36 import com.liferay.portal.kernel.events.SessionAction;
37 import com.liferay.portal.kernel.events.SimpleAction;
38 import com.liferay.portal.kernel.language.LanguageUtil;
39 import com.liferay.portal.kernel.log.Log;
40 import com.liferay.portal.kernel.log.LogFactoryUtil;
41 import com.liferay.portal.kernel.util.ArrayUtil;
42 import com.liferay.portal.kernel.util.FileUtil;
43 import com.liferay.portal.kernel.util.GetterUtil;
44 import com.liferay.portal.kernel.util.HttpUtil;
45 import com.liferay.portal.kernel.util.StringPool;
46 import com.liferay.portal.kernel.util.StringUtil;
47 import com.liferay.portal.kernel.util.Validator;
48 import com.liferay.portal.kernel.xml.Document;
49 import com.liferay.portal.kernel.xml.Element;
50 import com.liferay.portal.kernel.xml.SAXReaderUtil;
51 import com.liferay.portal.model.BaseModel;
52 import com.liferay.portal.model.ModelListener;
53 import com.liferay.portal.security.auth.AuthFailure;
54 import com.liferay.portal.security.auth.AuthPipeline;
55 import com.liferay.portal.security.auth.Authenticator;
56 import com.liferay.portal.security.auth.AutoLogin;
57 import com.liferay.portal.security.auth.CompanyThreadLocal;
58 import com.liferay.portal.security.ldap.AttributesTransformer;
59 import com.liferay.portal.security.ldap.AttributesTransformerFactory;
60 import com.liferay.portal.service.persistence.BasePersistence;
61 import com.liferay.portal.servlet.filters.autologin.AutoLoginFilter;
62 import com.liferay.portal.servlet.filters.cache.CacheUtil;
63 import com.liferay.portal.struts.MultiMessageResources;
64 import com.liferay.portal.struts.MultiMessageResourcesFactory;
65 import com.liferay.portal.util.PortalInstances;
66 import com.liferay.portal.util.PortalUtil;
67 import com.liferay.portal.util.PropsKeys;
68 import com.liferay.portal.util.PropsUtil;
69 import com.liferay.portal.util.PropsValues;
70
71 import java.io.File;
72 import java.io.InputStream;
73
74 import java.lang.reflect.Field;
75 import java.lang.reflect.Proxy;
76
77 import java.net.URL;
78
79 import java.util.ArrayList;
80 import java.util.HashMap;
81 import java.util.HashSet;
82 import java.util.Iterator;
83 import java.util.List;
84 import java.util.Map;
85 import java.util.Properties;
86 import java.util.Set;
87
88 import javax.servlet.ServletContext;
89
90
96 public class HookHotDeployListener
97 extends BaseHotDeployListener implements PropsKeys {
98
99 public void invokeDeploy(HotDeployEvent event) throws HotDeployException {
100 try {
101 doInvokeDeploy(event);
102 }
103 catch (Throwable t) {
104 throwHotDeployException(event, "Error registering hook for ", t);
105 }
106 }
107
108 public void invokeUndeploy(HotDeployEvent event) throws HotDeployException {
109 try {
110 doInvokeUndeploy(event);
111 }
112 catch (Throwable t) {
113 throwHotDeployException(event, "Error unregistering hook for ", t);
114 }
115 }
116
117 protected boolean containsKey(Properties portalProperties, String key) {
118 if (_log.isDebugEnabled()) {
119 return true;
120 }
121 else {
122 return portalProperties.containsKey(key);
123 }
124 }
125
126 protected void destroyCustomJspBag(CustomJspBag customJspBag) {
127 String customJspDir = customJspBag.getCustomJspDir();
128 List<String> customJsps = customJspBag.getCustomJsps();
129
131 String portalWebDir = PortalUtil.getPortalWebDir();
132
133 for (String customJsp : customJsps) {
134 int pos = customJsp.indexOf(customJspDir);
135
136 String portalJsp = customJsp.substring(
137 pos + customJspDir.length(), customJsp.length());
138
139 File portalJspFile = new File(portalWebDir + portalJsp);
140 File portalJspBackupFile = getPortalJspBackupFile(portalJspFile);
141
142 if (portalJspBackupFile.exists()) {
143 FileUtil.copyFile(portalJspBackupFile, portalJspFile);
144
145 portalJspBackupFile.delete();
146 }
147 else if (portalJspFile.exists()) {
148 portalJspFile.delete();
149 }
150 }
151 }
152
153 protected void destroyPortalProperties(Properties portalProperties)
154 throws Exception {
155
156 PropsUtil.removeProperties(portalProperties);
157
158 if (_log.isDebugEnabled() && portalProperties.containsKey(LOCALES)) {
159 _log.debug(
160 "Portlet locales " + portalProperties.getProperty(LOCALES));
161 _log.debug("Original locales " + PropsUtil.get(LOCALES));
162 _log.debug(
163 "Original locales array length " +
164 PropsUtil.getArray(LOCALES).length);
165 }
166
167 resetPortalProperties(portalProperties);
168
169 if (portalProperties.contains(PropsKeys.LDAP_ATTRS_TRANSFORMER_IMPL)) {
170 AttributesTransformerFactory.setInstance(null);
171 }
172 }
173
174 protected void doInvokeDeploy(HotDeployEvent event) throws Exception {
175 ServletContext servletContext = event.getServletContext();
176
177 String servletContextName = servletContext.getServletContextName();
178
179 if (_log.isDebugEnabled()) {
180 _log.debug("Invoking deploy for " + servletContextName);
181 }
182
183 String xml = HttpUtil.URLtoString(
184 servletContext.getResource("/WEB-INF/liferay-hook.xml"));
185
186 if (xml == null) {
187 return;
188 }
189
190 if (_log.isInfoEnabled()) {
191 _log.info("Registering hook for " + servletContextName);
192 }
193
194 _servletContextNames.add(servletContextName);
195
196 ClassLoader portletClassLoader = event.getContextClassLoader();
197
198 Document doc = SAXReaderUtil.read(xml, true);
199
200 Element root = doc.getRootElement();
201
202 String portalPropertiesLocation = root.elementText("portal-properties");
203
204 if (Validator.isNotNull(portalPropertiesLocation)) {
205 Configuration portalPropertiesConfiguration = null;
206
207 try {
208 String name = portalPropertiesLocation;
209
210 int pos = name.lastIndexOf(".properties");
211
212 if (pos != -1) {
213 name = name.substring(0, pos);
214 }
215
216 portalPropertiesConfiguration =
217 ConfigurationFactoryUtil.getConfiguration(
218 portletClassLoader, name);
219 }
220 catch (Exception e) {
221 _log.error("Unable to read " + portalPropertiesLocation, e);
222 }
223
224 if (portalPropertiesConfiguration != null) {
225 Properties portalProperties =
226 portalPropertiesConfiguration.getProperties();
227
228 if (portalProperties.size() > 0) {
229 _portalPropertiesMap.put(
230 servletContextName, portalProperties);
231
232
237 initPortalProperties(portletClassLoader, portalProperties);
238 initAuthFailures(
239 servletContextName, portletClassLoader,
240 portalProperties);
241 initAutoLogins(
242 servletContextName, portletClassLoader,
243 portalProperties);
244 initModelListeners(
245 servletContextName, portletClassLoader,
246 portalProperties);
247 initEvents(
248 servletContextName, portletClassLoader,
249 portalProperties);
250 }
251 }
252 }
253
254 LanguagesContainer languagesContainer = new LanguagesContainer();
255
256 _languagesContainerMap.put(servletContextName, languagesContainer);
257
258 List<Element> languagePropertiesEls = root.elements(
259 "language-properties");
260
261 for (Element languagePropertiesEl : languagePropertiesEls) {
262 String languagePropertiesLocation = languagePropertiesEl.getText();
263
264 try {
265 URL url = portletClassLoader.getResource(
266 languagePropertiesLocation);
267
268 if (url == null) {
269 continue;
270 }
271
272 InputStream is = url.openStream();
273
274 Properties properties = new Properties();
275
276 properties.load(is);
277
278 is.close();
279
280 String localeKey = getLocaleKey(languagePropertiesLocation);
281
282 if (localeKey != null) {
283 languagesContainer.addLanguage(localeKey, properties);
284 }
285 }
286 catch (Exception e) {
287 _log.error("Unable to read " + languagePropertiesLocation, e);
288 }
289 }
290
291 String customJspDir = root.elementText("custom-jsp-dir");
292
293 if (Validator.isNotNull(customJspDir)) {
294 if (_log.isDebugEnabled()) {
295 _log.debug("Custom JSP directory: " + customJspDir);
296 }
297
298 List<String> customJsps = new ArrayList<String>();
299
300 String webDir = servletContext.getRealPath(StringPool.SLASH);
301
302 getCustomJsps(servletContext, webDir, customJspDir, customJsps);
303
304 if (customJsps.size() > 0) {
305 CustomJspBag customJspBag = new CustomJspBag(
306 customJspDir, customJsps);
307
308 if (_log.isDebugEnabled()) {
309 StringBuilder sb = new StringBuilder();
310
311 sb.append("Custom JSP files:\n");
312
313 Iterator<String> itr = customJsps.iterator();
314
315 while (itr.hasNext()) {
316 String customJsp = itr.next();
317
318 sb.append(customJsp);
319
320 if (itr.hasNext()) {
321 sb.append(StringPool.NEW_LINE);
322 }
323 }
324
325 _log.debug(sb.toString());
326 }
327
328 _customJspBagsMap.put(servletContextName, customJspBag);
329
330 initCustomJspBag(customJspBag);
331 }
332 }
333
334
336 ModelListenersContainer modelListenersContainer =
337 _modelListenersContainerMap.get(servletContextName);
338
339 if (modelListenersContainer == null) {
340 modelListenersContainer = new ModelListenersContainer();
341
342 _modelListenersContainerMap.put(
343 servletContextName, modelListenersContainer);
344 }
345
346 List<Element> modelListenerEls = root.elements("model-listener");
347
348 for (Element modelListenerEl : modelListenerEls) {
349 String modelName = modelListenerEl.elementText("model-name");
350 String modelListenerClassName = modelListenerEl.elementText(
351 "model-listener-class");
352
353 ModelListener<BaseModel<?>> modelListener = initModelListener(
354 modelName, modelListenerClassName, portletClassLoader);
355
356 if (modelListener != null) {
357 modelListenersContainer.registerModelListener(
358 modelName, modelListener);
359 }
360 }
361
362 EventsContainer eventsContainer = _eventsContainerMap.get(
363 servletContextName);
364
365 if (eventsContainer == null) {
366 eventsContainer = new EventsContainer();
367
368 _eventsContainerMap.put(servletContextName, eventsContainer);
369 }
370
371 List<Element> eventEls = root.elements("event");
372
373 for (Element eventEl : eventEls) {
374 String eventName = eventEl.elementText("event-type");
375 String eventClassName = eventEl.elementText("event-class");
376
377 Object obj = initEvent(
378 eventName, eventClassName, portletClassLoader);
379
380 if (obj != null) {
381 eventsContainer.registerEvent(eventName, obj);
382 }
383 }
384
385
387 registerClpMessageListeners(servletContext, portletClassLoader);
388
389 if (_log.isInfoEnabled()) {
390 _log.info(
391 "Hook for " + servletContextName + " is available for use");
392 }
393 }
394
395 protected void doInvokeUndeploy(HotDeployEvent event) throws Exception {
396 ServletContext servletContext = event.getServletContext();
397
398 String servletContextName = servletContext.getServletContextName();
399
400 if (_log.isDebugEnabled()) {
401 _log.debug("Invoking undeploy for " + servletContextName);
402 }
403
404 if (!_servletContextNames.remove(servletContextName)) {
405 return;
406 }
407
408 AuthenticatorsContainer authenticatorsContainer =
409 _authenticatorsContainerMap.remove(servletContextName);
410
411 if (authenticatorsContainer != null) {
412 authenticatorsContainer.unregisterAuthenticators();
413 }
414
415 AuthFailuresContainer authFailuresContainer =
416 _authFailuresContainerMap.remove(servletContextName);
417
418 if (authFailuresContainer != null) {
419 authFailuresContainer.unregisterAuthFailures();
420 }
421
422 AutoLoginsContainer autoLoginsContainer =
423 _autoLoginsContainerMap.remove(servletContextName);
424
425 if (autoLoginsContainer != null) {
426 autoLoginsContainer.unregisterAutoLogins();
427 }
428
429 CustomJspBag customJspBag = _customJspBagsMap.remove(
430 servletContextName);
431
432 if (customJspBag != null) {
433 destroyCustomJspBag(customJspBag);
434 }
435
436 EventsContainer eventsContainer = _eventsContainerMap.remove(
437 servletContextName);
438
439 if (eventsContainer != null) {
440 eventsContainer.unregisterEvents();
441 }
442
443 LanguagesContainer languagesContainer = _languagesContainerMap.remove(
444 servletContextName);
445
446 if (languagesContainer != null) {
447 languagesContainer.unregisterLanguages();
448 }
449
450 ModelListenersContainer modelListenersContainer =
451 _modelListenersContainerMap.remove(servletContextName);
452
453 if (modelListenersContainer != null) {
454 modelListenersContainer.unregisterModelListeners();
455 }
456
457 Properties portalProperties = _portalPropertiesMap.remove(
458 servletContextName);
459
460 if (portalProperties != null) {
461 destroyPortalProperties(portalProperties);
462 }
463
464 unregisterClpMessageListeners(servletContext);
465
466 if (_log.isInfoEnabled()) {
467 _log.info("Hook for " + servletContextName + " was unregistered");
468 }
469 }
470
471 protected void getCustomJsps(
472 ServletContext servletContext, String webDir, String resourcePath,
473 List<String> customJsps) {
474
475 Set<String> resourcePaths = servletContext.getResourcePaths(
476 resourcePath);
477
478 for (String curResourcePath : resourcePaths) {
479 if (curResourcePath.endsWith(StringPool.SLASH)) {
480 getCustomJsps(
481 servletContext, webDir, curResourcePath, customJsps);
482 }
483 else {
484 String customJsp = webDir + curResourcePath;
485
486 customJsp = StringUtil.replace(
487 customJsp, StringPool.DOUBLE_SLASH, StringPool.SLASH);
488
489 customJsps.add(customJsp);
490 }
491 }
492 }
493
494 protected String getLocaleKey(String languagePropertiesLocation) {
495 String localeKey = null;
496
497 int x = languagePropertiesLocation.indexOf(StringPool.UNDERLINE);
498 int y = languagePropertiesLocation.indexOf(".properties");
499
500 if ((x != -1) && (y != 1)) {
501 localeKey = languagePropertiesLocation.substring(x + 1, y);
502 }
503
504 return localeKey;
505 }
506
507 protected BasePersistence getPersistence(String modelName) {
508 int pos = modelName.lastIndexOf(StringPool.PERIOD);
509
510 String entityName = modelName.substring(pos + 1);
511
512 pos = modelName.lastIndexOf(".model.");
513
514 String packagePath = modelName.substring(0, pos);
515
516 return (BasePersistence)PortalBeanLocatorUtil.locate(
517 packagePath + ".service.persistence." + entityName +
518 "Persistence.impl");
519 }
520
521 protected File getPortalJspBackupFile(File portalJspFile) {
522 String fileName = portalJspFile.toString();
523
524 if (fileName.endsWith(".jsp")) {
525 fileName =
526 fileName.substring(0, fileName.length() - 4) + ".portal.jsp";
527 }
528 else if (fileName.endsWith(".jspf")) {
529 fileName =
530 fileName.substring(0, fileName.length() - 5) + ".portal.jspf";
531 }
532
533 return new File(fileName);
534 }
535
536 protected void initAuthenticators(
537 ClassLoader portletClassLoader, Properties portalProperties,
538 String key, AuthenticatorsContainer authenticatorsContainer)
539 throws Exception {
540
541 String[] authenticatorClassNames = StringUtil.split(
542 portalProperties.getProperty(key));
543
544 for (String authenticatorClassName : authenticatorClassNames) {
545 Authenticator authenticator =
546 (Authenticator)portletClassLoader.loadClass(
547 authenticatorClassName).newInstance();
548
549 authenticator = (Authenticator)Proxy.newProxyInstance(
550 portletClassLoader, new Class[] {Authenticator.class},
551 new ContextClassLoaderBeanHandler(
552 authenticator, portletClassLoader));
553
554 authenticatorsContainer.registerAuthenticator(
555 key, authenticator);
556 }
557 }
558
559 protected void initAuthenticators(
560 String servletContextName, ClassLoader portletClassLoader,
561 Properties portalProperties)
562 throws Exception {
563
564 AuthenticatorsContainer authenticatorsContainer =
565 new AuthenticatorsContainer();
566
567 _authenticatorsContainerMap.put(
568 servletContextName, authenticatorsContainer);
569
570 initAuthenticators(
571 portletClassLoader, portalProperties, AUTH_PIPELINE_PRE,
572 authenticatorsContainer);
573 initAuthenticators(
574 portletClassLoader, portalProperties, AUTH_PIPELINE_POST,
575 authenticatorsContainer);
576 }
577
578 protected void initAuthFailures(
579 ClassLoader portletClassLoader, Properties portalProperties,
580 String key, AuthFailuresContainer authFailuresContainer)
581 throws Exception {
582
583 String[] authFailureClassNames = StringUtil.split(
584 portalProperties.getProperty(key));
585
586 for (String authFailureClassName : authFailureClassNames) {
587 AuthFailure authFailure = (AuthFailure)portletClassLoader.loadClass(
588 authFailureClassName).newInstance();
589
590 authFailure = (AuthFailure)Proxy.newProxyInstance(
591 portletClassLoader, new Class[] {AuthFailure.class},
592 new ContextClassLoaderBeanHandler(
593 authFailure, portletClassLoader));
594
595 authFailuresContainer.registerAuthFailure(
596 key, authFailure);
597 }
598 }
599
600 protected void initAuthFailures(
601 String servletContextName, ClassLoader portletClassLoader,
602 Properties portalProperties)
603 throws Exception {
604
605 AuthFailuresContainer authFailuresContainer =
606 new AuthFailuresContainer();
607
608 _authFailuresContainerMap.put(
609 servletContextName, authFailuresContainer);
610
611 initAuthFailures(
612 portletClassLoader, portalProperties, AUTH_FAILURE,
613 authFailuresContainer);
614 initAuthFailures(
615 portletClassLoader, portalProperties, AUTH_MAX_FAILURES,
616 authFailuresContainer);
617 }
618
619 protected void initAutoLogins(
620 String servletContextName, ClassLoader portletClassLoader,
621 Properties portalProperties)
622 throws Exception {
623
624 AutoLoginsContainer autoLoginsContainer = new AutoLoginsContainer();
625
626 _autoLoginsContainerMap.put(servletContextName, autoLoginsContainer);
627
628 String[] autoLoginClassNames = StringUtil.split(
629 portalProperties.getProperty(AUTO_LOGIN_HOOKS));
630
631 for (String autoLoginClassName : autoLoginClassNames) {
632 AutoLogin autoLogin = (AutoLogin)portletClassLoader.loadClass(
633 autoLoginClassName).newInstance();
634
635 autoLogin = (AutoLogin)Proxy.newProxyInstance(
636 portletClassLoader, new Class[] {AutoLogin.class},
637 new ContextClassLoaderBeanHandler(
638 autoLogin, portletClassLoader));
639
640 autoLoginsContainer.registerAutoLogin(autoLogin);
641 }
642 }
643
644 protected void initCustomJspBag(CustomJspBag customJspBag)
645 throws Exception {
646
647 String customJspDir = customJspBag.getCustomJspDir();
648 List<String> customJsps = customJspBag.getCustomJsps();
649
651 String portalWebDir = PortalUtil.getPortalWebDir();
652
653 for (String customJsp : customJsps) {
654 int pos = customJsp.indexOf(customJspDir);
655
656 String portalJsp = customJsp.substring(
657 pos + customJspDir.length(), customJsp.length());
658
659 File portalJspFile = new File(portalWebDir + portalJsp);
660 File portalJspBackupFile = getPortalJspBackupFile(portalJspFile);
661
662 if (portalJspFile.exists() && !portalJspBackupFile.exists()) {
663 FileUtil.copyFile(portalJspFile, portalJspBackupFile);
664 }
665
666 String customJspContent = FileUtil.read(customJsp);
667
668 FileUtil.write(portalJspFile, customJspContent);
669 }
670 }
671
672 protected Object initEvent(
673 String eventName, String eventClassName,
674 ClassLoader portletClassLoader)
675 throws Exception {
676
677 if (eventName.equals(APPLICATION_STARTUP_EVENTS)) {
678 SimpleAction simpleAction =
679 (SimpleAction)portletClassLoader.loadClass(
680 eventClassName).newInstance();
681
682 simpleAction = new InvokerSimpleAction(
683 simpleAction, portletClassLoader);
684
685 long companyId = CompanyThreadLocal.getCompanyId();
686
687 long[] companyIds = PortalInstances.getCompanyIds();
688
689 for (long curCompanyId : companyIds) {
690 CompanyThreadLocal.setCompanyId(curCompanyId);
691
692 simpleAction.run(new String[] {String.valueOf(curCompanyId)});
693 }
694
695 CompanyThreadLocal.setCompanyId(companyId);
696
697 return null;
698 }
699
700 if (ArrayUtil.contains(_PROPS_KEYS_EVENTS, eventName)) {
701 Action action = (Action)portletClassLoader.loadClass(
702 eventClassName).newInstance();
703
704 action = new InvokerAction(action, portletClassLoader);
705
706 EventsProcessorUtil.registerEvent(eventName, action);
707
708 return action;
709 }
710
711 if (ArrayUtil.contains(_PROPS_KEYS_SESSION_EVENTS, eventName)) {
712 SessionAction sessionAction =
713 (SessionAction)portletClassLoader.loadClass(
714 eventClassName).newInstance();
715
716 sessionAction = new InvokerSessionAction(
717 sessionAction, portletClassLoader);
718
719 EventsProcessorUtil.registerEvent(eventName, sessionAction);
720
721 return sessionAction;
722 }
723
724 return null;
725 }
726
727 protected void initEvents(
728 String servletContextName, ClassLoader portletClassLoader,
729 Properties portalProperties)
730 throws Exception {
731
732 EventsContainer eventsContainer = new EventsContainer();
733
734 _eventsContainerMap.put(servletContextName, eventsContainer);
735
736 Iterator<Object> itr = portalProperties.keySet().iterator();
737
738 while (itr.hasNext()) {
739 String key = (String)itr.next();
740
741 if (!key.equals(APPLICATION_STARTUP_EVENTS) &&
742 !ArrayUtil.contains(_PROPS_KEYS_EVENTS, key) &&
743 !ArrayUtil.contains(_PROPS_KEYS_SESSION_EVENTS, key)) {
744
745 continue;
746 }
747
748 String eventName = key;
749 String[] eventClassNames = StringUtil.split(
750 portalProperties.getProperty(key));
751
752 for (String eventClassName : eventClassNames) {
753 Object obj = initEvent(
754 eventName, eventClassName, portletClassLoader);
755
756 if (obj == null) {
757 continue;
758 }
759
760 eventsContainer.registerEvent(eventName, obj);
761 }
762 }
763 }
764
765 protected ModelListener<BaseModel<?>> initModelListener(
766 String modelName, String modelListenerClassName,
767 ClassLoader portletClassLoader)
768 throws Exception {
769
770 ModelListener<BaseModel<?>> modelListener =
771 (ModelListener<BaseModel<?>>)portletClassLoader.loadClass(
772 modelListenerClassName).newInstance();
773
774 modelListener = (ModelListener<BaseModel<?>>)Proxy.newProxyInstance(
775 portletClassLoader, new Class[] {ModelListener.class},
776 new ContextClassLoaderBeanHandler(
777 modelListener, portletClassLoader));
778
779 BasePersistence persistence = getPersistence(modelName);
780
781 persistence.registerListener(modelListener);
782
783 return modelListener;
784 }
785
786 protected void initModelListeners(
787 String servletContextName, ClassLoader portletClassLoader,
788 Properties portalProperties)
789 throws Exception {
790
791 ModelListenersContainer modelListenersContainer =
792 new ModelListenersContainer();
793
794 _modelListenersContainerMap.put(
795 servletContextName, modelListenersContainer);
796
797 Iterator<Object> itr = portalProperties.keySet().iterator();
798
799 while (itr.hasNext()) {
800 String key = (String)itr.next();
801
802 if (!key.startsWith(VALUE_OBJECT_LISTENER)) {
803 continue;
804 }
805
806 String modelName = key.substring(VALUE_OBJECT_LISTENER.length());
807 String modelListenerClassName = portalProperties.getProperty(key);
808
809 ModelListener<BaseModel<?>> modelListener = initModelListener(
810 modelName, modelListenerClassName, portletClassLoader);
811
812 if (modelListener != null) {
813 modelListenersContainer.registerModelListener(
814 modelName, modelListener);
815 }
816 }
817 }
818
819 protected void initPortalProperties(
820 ClassLoader portletClassLoader, Properties portalProperties)
821 throws Exception {
822
823 PropsUtil.addProperties(portalProperties);
824
825 if (_log.isDebugEnabled() && portalProperties.containsKey(LOCALES)) {
826 _log.debug(
827 "Portlet locales " + portalProperties.getProperty(LOCALES));
828 _log.debug("Merged locales " + PropsUtil.get(LOCALES));
829 _log.debug(
830 "Merged locales array length " +
831 PropsUtil.getArray(LOCALES).length);
832 }
833
834 resetPortalProperties(portalProperties);
835
836 if (portalProperties.contains(PropsKeys.LDAP_ATTRS_TRANSFORMER_IMPL)) {
837 String attributesTransformerClassName =
838 portalProperties.getProperty(
839 PropsKeys.LDAP_ATTRS_TRANSFORMER_IMPL);
840
841 AttributesTransformer attributesTransformer =
842 (AttributesTransformer)portletClassLoader.loadClass(
843 attributesTransformerClassName).newInstance();
844
845 attributesTransformer =
846 (AttributesTransformer)Proxy.newProxyInstance(
847 portletClassLoader,
848 new Class[] {AttributesTransformer.class},
849 new ContextClassLoaderBeanHandler(
850 attributesTransformer, portletClassLoader));
851
852 AttributesTransformerFactory.setInstance(attributesTransformer);
853 }
854 }
855
856 protected void resetPortalProperties(Properties portalProperties)
857 throws Exception {
858
859 for (String key : _PROPS_VALUES_BOOLEAN) {
860 String fieldName = StringUtil.replace(
861 key.toUpperCase(), StringPool.PERIOD, StringPool.UNDERLINE);
862
863 if (!containsKey(portalProperties, key)) {
864 continue;
865 }
866
867 try {
868 Field field = PropsValues.class.getField(fieldName);
869
870 Boolean value = Boolean.valueOf(GetterUtil.getBoolean(
871 PropsUtil.get(key)));
872
873 field.setBoolean(null, value);
874 }
875 catch (Exception e) {
876 _log.error(
877 "Error setting field " + fieldName + ": " + e.getMessage());
878 }
879 }
880
881 for (String key : _PROPS_VALUES_INTEGER) {
882 String fieldName = StringUtil.replace(
883 key.toUpperCase(), StringPool.PERIOD, StringPool.UNDERLINE);
884
885 if (!containsKey(portalProperties, key)) {
886 continue;
887 }
888
889 try {
890 Field field = PropsValues.class.getField(fieldName);
891
892 Integer value = Integer.valueOf(GetterUtil.getInteger(
893 PropsUtil.get(key)));
894
895 field.setInt(null, value);
896 }
897 catch (Exception e) {
898 _log.error(
899 "Error setting field " + fieldName + ": " + e.getMessage());
900 }
901 }
902
903 for (String key : _PROPS_VALUES_LONG) {
904 String fieldName = StringUtil.replace(
905 key.toUpperCase(), StringPool.PERIOD, StringPool.UNDERLINE);
906
907 if (!containsKey(portalProperties, key)) {
908 continue;
909 }
910
911 try {
912 Field field = PropsValues.class.getField(fieldName);
913
914 Long value = Long.valueOf(GetterUtil.getLong(
915 PropsUtil.get(key)));
916
917 field.setLong(null, value);
918 }
919 catch (Exception e) {
920 _log.error(
921 "Error setting field " + fieldName + ": " + e.getMessage());
922 }
923 }
924
925 for (String key : _PROPS_VALUES_STRING) {
926 String fieldName = StringUtil.replace(
927 key.toUpperCase(), StringPool.PERIOD, StringPool.UNDERLINE);
928
929 if (!containsKey(portalProperties, key)) {
930 continue;
931 }
932
933 try {
934 Field field = PropsValues.class.getField(fieldName);
935
936 String value = GetterUtil.getString(PropsUtil.get(key));
937
938 field.set(null, value);
939 }
940 catch (Exception e) {
941 _log.error(
942 "Error setting field " + fieldName + ": " + e.getMessage());
943 }
944 }
945
946 for (String key : _PROPS_VALUES_STRING_ARRAY) {
947 String fieldName = StringUtil.replace(
948 key.toUpperCase(), StringPool.PERIOD, StringPool.UNDERLINE);
949
950 if (!containsKey(portalProperties, key)) {
951 continue;
952 }
953
954 try {
955 Field field = PropsValues.class.getField(fieldName);
956
957 String[] value = PropsUtil.getArray(key);
958
959 field.set(null, value);
960 }
961 catch (Exception e) {
962 _log.error(
963 "Error setting field " + fieldName + ": " + e.getMessage());
964 }
965 }
966
967 if (containsKey(portalProperties, LOCALES)) {
968 PropsValues.LOCALES = PropsUtil.getArray(LOCALES);
969
970 LanguageUtil.init();
971 }
972
973 CacheUtil.clearCache();
974 }
975
976 private static final String[] _PROPS_KEYS_EVENTS = new String[] {
977 LOGIN_EVENTS_POST,
978 LOGIN_EVENTS_PRE,
979 LOGOUT_EVENTS_POST,
980 LOGOUT_EVENTS_PRE,
981 SERVLET_SERVICE_EVENTS_POST,
982 SERVLET_SERVICE_EVENTS_PRE
983 };
984
985 private static final String[] _PROPS_KEYS_SESSION_EVENTS = new String[] {
986 SERVLET_SESSION_CREATE_EVENTS,
987 SERVLET_SESSION_DESTROY_EVENTS
988 };
989
990 private static final String[] _PROPS_VALUES_BOOLEAN = new String[] {
991 "auth.forward.by.last.path",
992 "captcha.check.portal.create_account",
993 "field.enable.com.liferay.portal.model.Contact.birthday",
994 "field.enable.com.liferay.portal.model.Contact.male",
995 "field.enable.com.liferay.portal.model.Organization.status",
996 "javascript.fast.load",
997 "layout.template.cache.enabled",
998 "layout.user.private.layouts.auto.create",
999 "layout.user.private.layouts.enabled",
1000 "layout.user.private.layouts.modifiable",
1001 "layout.user.public.layouts.auto.create",
1002 "layout.user.public.layouts.enabled",
1003 "layout.user.public.layouts.modifiable",
1004 "login.create.account.allow.custom.password",
1005 "my.places.show.community.private.sites.with.no.layouts",
1006 "my.places.show.community.public.sites.with.no.layouts",
1007 "my.places.show.organization.private.sites.with.no.layouts",
1008 "my.places.show.organization.public.sites.with.no.layouts",
1009 "my.places.show.user.private.sites.with.no.layouts",
1010 "my.places.show.user.public.sites.with.no.layouts",
1011 "terms.of.use.required",
1012 "theme.css.fast.load",
1013 "theme.images.fast.load"
1014 };
1015
1016 private static final String[] _PROPS_VALUES_INTEGER = new String[] {
1017 };
1018
1019 private static final String[] _PROPS_VALUES_LONG = new String[] {
1020 };
1021
1022 private static final String[] _PROPS_VALUES_STRING = new String[] {
1023 "default.landing.page.path",
1024 "passwords.passwordpolicytoolkit.generator",
1025 "passwords.passwordpolicytoolkit.static"
1026 };
1027
1028 private static final String[] _PROPS_VALUES_STRING_ARRAY = new String[] {
1029 "layout.static.portlets.all",
1030 "session.phishing.protected.attributes"
1031 };
1032
1033 private static Log _log =
1034 LogFactoryUtil.getLog(HookHotDeployListener.class);
1035
1036 private Map<String, AuthenticatorsContainer> _authenticatorsContainerMap =
1037 new HashMap<String, AuthenticatorsContainer>();
1038 private Map<String, AuthFailuresContainer> _authFailuresContainerMap =
1039 new HashMap<String, AuthFailuresContainer>();
1040 private Map<String, AutoLoginsContainer> _autoLoginsContainerMap =
1041 new HashMap<String, AutoLoginsContainer>();
1042 private Map<String, CustomJspBag> _customJspBagsMap =
1043 new HashMap<String, CustomJspBag>();
1044 private Map<String, EventsContainer> _eventsContainerMap =
1045 new HashMap<String, EventsContainer>();
1046 private Map<String, LanguagesContainer> _languagesContainerMap =
1047 new HashMap<String, LanguagesContainer>();
1048 private Map<String, ModelListenersContainer> _modelListenersContainerMap =
1049 new HashMap<String, ModelListenersContainer>();
1050 private Map<String, Properties> _portalPropertiesMap =
1051 new HashMap<String, Properties>();
1052 private Set<String> _servletContextNames = new HashSet<String>();
1053
1054 private class AuthenticatorsContainer {
1055
1056 public void registerAuthenticator(
1057 String key, Authenticator authenticator) {
1058
1059 List<Authenticator> authenticators = _authenticators.get(key);
1060
1061 if (authenticators == null) {
1062 authenticators = new ArrayList<Authenticator>();
1063
1064 _authenticators.put(key, authenticators);
1065 }
1066
1067 AuthPipeline.registerAuthenticator(key, authenticator);
1068
1069 authenticators.add(authenticator);
1070 }
1071
1072 public void unregisterAuthenticators() {
1073 for (Map.Entry<String, List<Authenticator>> entry :
1074 _authenticators.entrySet()) {
1075
1076 String key = entry.getKey();
1077 List<Authenticator> authenticators = entry.getValue();
1078
1079 for (Authenticator authenticator : authenticators) {
1080 AuthPipeline.unregisterAuthenticator(key, authenticator);
1081 }
1082 }
1083 }
1084
1085 Map<String, List<Authenticator>> _authenticators =
1086 new HashMap<String, List<Authenticator>>();
1087
1088 }
1089
1090 private class AuthFailuresContainer {
1091
1092 public void registerAuthFailure(String key, AuthFailure authFailure) {
1093 List<AuthFailure> authFailures = _authFailures.get(key);
1094
1095 if (authFailures == null) {
1096 authFailures = new ArrayList<AuthFailure>();
1097
1098 _authFailures.put(key, authFailures);
1099 }
1100
1101 AuthPipeline.registerAuthFailure(key, authFailure);
1102
1103 authFailures.add(authFailure);
1104 }
1105
1106 public void unregisterAuthFailures() {
1107 for (Map.Entry<String, List<AuthFailure>> entry :
1108 _authFailures.entrySet()) {
1109
1110 String key = entry.getKey();
1111 List<AuthFailure> authFailures = entry.getValue();
1112
1113 for (AuthFailure authFailure : authFailures) {
1114 AuthPipeline.unregisterAuthFailure(key, authFailure);
1115 }
1116 }
1117 }
1118
1119 Map<String, List<AuthFailure>> _authFailures =
1120 new HashMap<String, List<AuthFailure>>();
1121
1122 }
1123
1124 private class AutoLoginsContainer {
1125
1126 public void registerAutoLogin(AutoLogin autoLogin) {
1127 AutoLoginFilter.registerAutoLogin(autoLogin);
1128
1129 _autoLogins.add(autoLogin);
1130 }
1131
1132 public void unregisterAutoLogins() {
1133 for (AutoLogin autoLogin : _autoLogins) {
1134 AutoLoginFilter.unregisterAutoLogin(autoLogin);
1135 }
1136 }
1137
1138 List<AutoLogin> _autoLogins = new ArrayList<AutoLogin>();
1139
1140 }
1141
1142 private class CustomJspBag {
1143
1144 public CustomJspBag(String customJspDir, List<String> customJsps) {
1145 _customJspDir = customJspDir;
1146 _customJsps = customJsps;
1147 }
1148
1149 public String getCustomJspDir() {
1150 return _customJspDir;
1151 }
1152
1153 public List<String> getCustomJsps() {
1154 return _customJsps;
1155 }
1156
1157 private String _customJspDir;
1158 private List<String> _customJsps;
1159
1160 }
1161
1162 private class EventsContainer {
1163
1164 public void registerEvent(String eventName, Object event) {
1165 List<Object> events = _eventsMap.get(eventName);
1166
1167 if (events == null) {
1168 events = new ArrayList<Object>();
1169
1170 _eventsMap.put(eventName, events);
1171 }
1172
1173 events.add(event);
1174 }
1175
1176 public void unregisterEvents() {
1177 for (Map.Entry<String, List<Object>> entry :
1178 _eventsMap.entrySet()) {
1179
1180 String eventName = entry.getKey();
1181 List<Object> events = entry.getValue();
1182
1183 for (Object event : events) {
1184 EventsProcessorUtil.unregisterEvent(eventName, event);
1185 }
1186 }
1187 }
1188
1189 private Map<String, List<Object>> _eventsMap =
1190 new HashMap<String, List<Object>>();
1191
1192 }
1193
1194 private class LanguagesContainer {
1195
1196 public void addLanguage(String localeKey, Properties properties) {
1197 _multiMessageResources.putLocale(localeKey);
1198
1199 Properties oldProperties = _multiMessageResources.putMessages(
1200 properties, localeKey);
1201
1202 _languagesMap.put(localeKey, oldProperties);
1203 }
1204
1205 public void unregisterLanguages() {
1206 for (String key : _languagesMap.keySet()) {
1207 Properties properties = _languagesMap.get(key);
1208
1209 _multiMessageResources.putMessages(properties, key);
1210 }
1211 }
1212
1213 private Map<String, Properties> _languagesMap =
1214 new HashMap<String, Properties>();
1215 private MultiMessageResources _multiMessageResources =
1216 MultiMessageResourcesFactory.getInstance();
1217
1218 }
1219
1220 private class ModelListenersContainer {
1221
1222 public void registerModelListener(
1223 String modelName, ModelListener<BaseModel<?>> modelListener) {
1224
1225 List<ModelListener<BaseModel<?>>> modelListeners =
1226 _modelListenersMap.get(modelName);
1227
1228 if (modelListeners == null) {
1229 modelListeners = new ArrayList<ModelListener<BaseModel<?>>>();
1230
1231 _modelListenersMap.put(modelName, modelListeners);
1232 }
1233
1234 modelListeners.add(modelListener);
1235 }
1236
1237 public void unregisterModelListeners() {
1238 for (Map.Entry<String, List<ModelListener<BaseModel<?>>>> entry :
1239 _modelListenersMap.entrySet()) {
1240
1241 String modelName = entry.getKey();
1242 List<ModelListener<BaseModel<?>>> modelListeners =
1243 entry.getValue();
1244
1245 BasePersistence persistence = getPersistence(modelName);
1246
1247 for (ModelListener<BaseModel<?>> modelListener :
1248 modelListeners) {
1249
1250 persistence.unregisterListener(modelListener);
1251 }
1252 }
1253 }
1254
1255 private Map<String, List<ModelListener<BaseModel<?>>>>
1256 _modelListenersMap =
1257 new HashMap<String, List<ModelListener<BaseModel<?>>>>();
1258
1259 }
1260
1261}