1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.deploy.hot;
24  
25  import com.liferay.portal.events.EventsProcessor;
26  import com.liferay.portal.kernel.bean.PortalBeanLocatorUtil;
27  import com.liferay.portal.kernel.configuration.Configuration;
28  import com.liferay.portal.kernel.configuration.ConfigurationFactoryUtil;
29  import com.liferay.portal.kernel.deploy.hot.HotDeployEvent;
30  import com.liferay.portal.kernel.deploy.hot.HotDeployException;
31  import com.liferay.portal.kernel.events.Action;
32  import com.liferay.portal.kernel.events.ActionWrapper;
33  import com.liferay.portal.kernel.events.InvokerSimpleAction;
34  import com.liferay.portal.kernel.events.SimpleAction;
35  import com.liferay.portal.kernel.events.SimpleActionWrapper;
36  import com.liferay.portal.kernel.language.LanguageUtil;
37  import com.liferay.portal.kernel.log.Log;
38  import com.liferay.portal.kernel.log.LogFactoryUtil;
39  import com.liferay.portal.kernel.util.ArrayUtil;
40  import com.liferay.portal.kernel.util.FileUtil;
41  import com.liferay.portal.kernel.util.GetterUtil;
42  import com.liferay.portal.kernel.util.HttpUtil;
43  import com.liferay.portal.kernel.util.StringPool;
44  import com.liferay.portal.kernel.util.StringUtil;
45  import com.liferay.portal.kernel.util.Time;
46  import com.liferay.portal.kernel.util.Validator;
47  import com.liferay.portal.kernel.xml.Document;
48  import com.liferay.portal.kernel.xml.Element;
49  import com.liferay.portal.kernel.xml.SAXReaderUtil;
50  import com.liferay.portal.model.ModelListener;
51  import com.liferay.portal.model.ModelListenerWrapper;
52  import com.liferay.portal.security.auth.AutoLogin;
53  import com.liferay.portal.security.auth.AutoLoginWrapper;
54  import com.liferay.portal.security.auth.CompanyThreadLocal;
55  import com.liferay.portal.service.persistence.BasePersistence;
56  import com.liferay.portal.servlet.filters.autologin.AutoLoginFilter;
57  import com.liferay.portal.servlet.filters.cache.CacheUtil;
58  import com.liferay.portal.struts.MultiMessageResources;
59  import com.liferay.portal.struts.MultiMessageResourcesFactory;
60  import com.liferay.portal.util.PortalInstances;
61  import com.liferay.portal.util.PortalUtil;
62  import com.liferay.portal.util.PropsKeys;
63  import com.liferay.portal.util.PropsUtil;
64  import com.liferay.portal.util.PropsValues;
65  
66  import java.io.File;
67  import java.io.InputStream;
68  
69  import java.lang.reflect.Field;
70  
71  import java.net.URL;
72  
73  import java.util.ArrayList;
74  import java.util.HashMap;
75  import java.util.HashSet;
76  import java.util.Iterator;
77  import java.util.List;
78  import java.util.Map;
79  import java.util.Properties;
80  import java.util.Set;
81  
82  import javax.servlet.ServletContext;
83  
84  /**
85   * <a href="HookHotDeployListener.java.html"><b><i>View Source</i></b></a>
86   *
87   * @author Brian Wing Shun Chan
88   * @author Bruno Farache
89   *
90   */
91  public class HookHotDeployListener
92      extends BaseHotDeployListener implements PropsKeys {
93  
94      public void invokeDeploy(HotDeployEvent event) throws HotDeployException {
95          try {
96              doInvokeDeploy(event);
97          }
98          catch (Throwable t) {
99              throwHotDeployException(event, "Error registering hook for ", t);
100         }
101     }
102 
103     public void invokeUndeploy(HotDeployEvent event) throws HotDeployException {
104         try {
105             doInvokeUndeploy(event);
106         }
107         catch (Throwable t) {
108             throwHotDeployException(event, "Error unregistering hook for ", t);
109         }
110     }
111 
112     protected boolean containsKey(Properties portalProperties, String key) {
113         if (_log.isDebugEnabled()) {
114             return true;
115         }
116         else {
117             return portalProperties.containsKey(key);
118         }
119     }
120 
121     protected void destroyCustomJspBag(CustomJspBag customJspBag) {
122         String customJspDir = customJspBag.getCustomJspDir();
123         List<String> customJsps = customJspBag.getCustomJsps();
124         //String timestamp = customJspBag.getTimestamp();
125 
126         String portalWebDir = PortalUtil.getPortalWebDir();
127 
128         for (String customJsp : customJsps) {
129             int pos = customJsp.indexOf(customJspDir);
130 
131             String portalJsp = customJsp.substring(
132                 pos + customJspDir.length(), customJsp.length());
133 
134             File portalJspFile = new File(portalWebDir + portalJsp);
135             File portalJspBackupFile = getPortalJspBackupFile(portalJspFile);
136 
137             if (portalJspBackupFile.exists()) {
138                 FileUtil.copyFile(portalJspBackupFile, portalJspFile);
139 
140                 portalJspBackupFile.delete();
141             }
142             else if (portalJspFile.exists()) {
143                 portalJspFile.delete();
144             }
145         }
146     }
147 
148     protected void destroyPortalProperties(Properties portalProperties)
149         throws Exception {
150 
151         PropsUtil.removeProperties(portalProperties);
152 
153         if (_log.isDebugEnabled() && portalProperties.containsKey(LOCALES)) {
154             _log.debug(
155                 "Portlet locales " + portalProperties.getProperty(LOCALES));
156             _log.debug("Original locales " + PropsUtil.get(LOCALES));
157             _log.debug(
158                 "Original locales array length " +
159                     PropsUtil.getArray(LOCALES).length);
160         }
161 
162         resetPortalProperties(portalProperties);
163     }
164 
165     protected void doInvokeDeploy(HotDeployEvent event) throws Exception {
166         ServletContext servletContext = event.getServletContext();
167 
168         String servletContextName = servletContext.getServletContextName();
169 
170         if (_log.isDebugEnabled()) {
171             _log.debug("Invoking deploy for " + servletContextName);
172         }
173 
174         String xml = HttpUtil.URLtoString(
175             servletContext.getResource("/WEB-INF/liferay-hook.xml"));
176 
177         if (xml == null) {
178             return;
179         }
180 
181         if (_log.isInfoEnabled()) {
182             _log.info("Registering hook for " + servletContextName);
183         }
184 
185         _servletContextNames.add(servletContextName);
186 
187         ClassLoader portletClassLoader = event.getContextClassLoader();
188 
189         Document doc = SAXReaderUtil.read(xml, true);
190 
191         Element root = doc.getRootElement();
192 
193         String portalPropertiesLocation = root.elementText("portal-properties");
194 
195         if (Validator.isNotNull(portalPropertiesLocation)) {
196             Configuration portalPropertiesConfiguration = null;
197 
198             try {
199                 String name = portalPropertiesLocation;
200 
201                 int pos = name.lastIndexOf(".properties");
202 
203                 if (pos != -1) {
204                     name = name.substring(0, pos);
205                 }
206 
207                 portalPropertiesConfiguration =
208                     ConfigurationFactoryUtil.getConfiguration(
209                         portletClassLoader, name);
210             }
211             catch (Exception e) {
212                 _log.error("Unable to read " + portalPropertiesLocation, e);
213             }
214 
215             if (portalPropertiesConfiguration != null) {
216                 Properties portalProperties =
217                     portalPropertiesConfiguration.getProperties();
218 
219                 if (portalProperties.size() > 0) {
220                     _portalPropertiesMap.put(
221                         servletContextName, portalProperties);
222 
223                     // Initialize properties, auto logins, model listeners, and
224                     // events in that specific order. Events have to be loaded
225                     // last because they may require model listeners to have
226                     // been registered.
227 
228                     initPortalProperties(portalProperties);
229                     initAutoLogins(
230                         servletContextName, portletClassLoader,
231                         portalProperties);
232                     initModelListeners(
233                         servletContextName, portletClassLoader,
234                         portalProperties);
235                     initEvents(
236                         servletContextName, portletClassLoader,
237                         portalProperties);
238                 }
239             }
240         }
241 
242         LanguagesContainer languagesContainer = new LanguagesContainer();
243 
244         _languagesContainerMap.put(servletContextName, languagesContainer);
245 
246         List<Element> languagePropertiesEls = root.elements(
247             "language-properties");
248 
249         for (Element languagePropertiesEl : languagePropertiesEls) {
250             String languagePropertiesLocation = languagePropertiesEl.getText();
251 
252             try {
253                 URL url = portletClassLoader.getResource(
254                     languagePropertiesLocation);
255 
256                 if (url == null) {
257                     continue;
258                 }
259 
260                 InputStream is = url.openStream();
261 
262                 Properties properties = new Properties();
263 
264                 properties.load(is);
265 
266                 is.close();
267 
268                 String localeKey = getLocaleKey(languagePropertiesLocation);
269 
270                 if (localeKey != null) {
271                     languagesContainer.addLanguage(localeKey, properties);
272                 }
273             }
274             catch (Exception e) {
275                 _log.error("Unable to read " + languagePropertiesLocation, e);
276             }
277         }
278 
279         String customJspDir = root.elementText("custom-jsp-dir");
280 
281         if (Validator.isNotNull(customJspDir)) {
282             if (_log.isDebugEnabled()) {
283                 _log.debug("Custom JSP directory: " + customJspDir);
284             }
285 
286             List<String> customJsps = new ArrayList<String>();
287 
288             String webDir = servletContext.getRealPath(StringPool.SLASH);
289 
290             getCustomJsps(servletContext, webDir, customJspDir, customJsps);
291 
292             if (customJsps.size() > 0) {
293                 CustomJspBag customJspBag = new CustomJspBag(
294                     customJspDir, customJsps);
295 
296                 if (_log.isDebugEnabled()) {
297                     StringBuilder sb = new StringBuilder();
298 
299                     sb.append("Custom JSP files:\n");
300 
301                     Iterator<String> itr = customJsps.iterator();
302 
303                     while (itr.hasNext()) {
304                         String customJsp = itr.next();
305 
306                         sb.append(customJsp);
307 
308                         if (itr.hasNext()) {
309                             sb.append(StringPool.NEW_LINE);
310                         }
311                     }
312 
313                     _log.debug(sb.toString());
314                 }
315 
316                 _customJspBagsMap.put(servletContextName, customJspBag);
317 
318                 initCustomJspBag(customJspBag);
319             }
320         }
321 
322         // Begin backwards compatibility for 5.1.0
323 
324         ModelListenersContainer modelListenersContainer =
325             _modelListenersContainerMap.get(servletContextName);
326 
327         if (modelListenersContainer == null) {
328             modelListenersContainer = new ModelListenersContainer();
329 
330             _modelListenersContainerMap.put(
331                 servletContextName, modelListenersContainer);
332         }
333 
334         List<Element> modelListenerEls = root.elements("model-listener");
335 
336         for (Element modelListenerEl : modelListenerEls) {
337             String modelName = modelListenerEl.elementText("model-name");
338             String modelListenerClass = modelListenerEl.elementText(
339                 "model-listener-class");
340 
341             ModelListener modelListener = initModelListener(
342                 modelName, modelListenerClass, portletClassLoader);
343 
344             if (modelListener != null) {
345                 modelListenersContainer.registerModelListener(
346                     modelName, modelListener);
347             }
348         }
349 
350         EventsContainer eventsContainer = _eventsContainerMap.get(
351             servletContextName);
352 
353         if (eventsContainer == null) {
354             eventsContainer = new EventsContainer();
355 
356             _eventsContainerMap.put(servletContextName, eventsContainer);
357         }
358 
359         List<Element> eventEls = root.elements("event");
360 
361         for (Element eventEl : eventEls) {
362             String eventName = eventEl.elementText("event-type");
363             String eventClass = eventEl.elementText("event-class");
364 
365             Object obj = initEvent(eventName, eventClass, portletClassLoader);
366 
367             if (obj != null) {
368                 eventsContainer.registerEvent(eventName, obj);
369             }
370         }
371 
372         // End backwards compatibility for 5.1.0
373 
374         if (_log.isInfoEnabled()) {
375             _log.info(
376                 "Hook for " + servletContextName + " is available for use");
377         }
378     }
379 
380     protected void doInvokeUndeploy(HotDeployEvent event) throws Exception {
381         ServletContext servletContext = event.getServletContext();
382 
383         String servletContextName = servletContext.getServletContextName();
384 
385         if (_log.isDebugEnabled()) {
386             _log.debug("Invoking undeploy for " + servletContextName);
387         }
388 
389         if (!_servletContextNames.remove(servletContextName)) {
390             return;
391         }
392 
393         AutoLoginsContainer autoLoginsContainer =
394             _autoLoginsContainerMap.remove(servletContextName);
395 
396         if (autoLoginsContainer != null) {
397             autoLoginsContainer.unregisterAutoLogins();
398         }
399 
400         CustomJspBag customJspBag = _customJspBagsMap.remove(
401             servletContextName);
402 
403         if (customJspBag != null) {
404             destroyCustomJspBag(customJspBag);
405         }
406 
407         EventsContainer eventsContainer = _eventsContainerMap.remove(
408             servletContextName);
409 
410         if (eventsContainer != null) {
411             eventsContainer.unregisterEvents();
412         }
413 
414         LanguagesContainer languagesContainer = _languagesContainerMap.remove(
415             servletContextName);
416 
417         if (languagesContainer != null) {
418             languagesContainer.unregisterLanguages();
419         }
420 
421         ModelListenersContainer modelListenersContainer =
422             _modelListenersContainerMap.remove(servletContextName);
423 
424         if (modelListenersContainer != null) {
425             modelListenersContainer.unregisterModelListeners();
426         }
427 
428         Properties portalProperties = _portalPropertiesMap.remove(
429             servletContextName);
430 
431         if (portalProperties != null) {
432             destroyPortalProperties(portalProperties);
433         }
434 
435         if (_log.isInfoEnabled()) {
436             _log.info("Hook for " + servletContextName + " was unregistered");
437         }
438     }
439 
440     protected void getCustomJsps(
441         ServletContext servletContext, String webDir, String resourcePath,
442         List<String> customJsps) {
443 
444         Set<String> resourcePaths = servletContext.getResourcePaths(
445             resourcePath);
446 
447         for (String curResourcePath : resourcePaths) {
448             if (curResourcePath.endsWith(StringPool.SLASH)) {
449                 getCustomJsps(
450                     servletContext, webDir, curResourcePath, customJsps);
451             }
452             else {
453                 String customJsp = webDir + curResourcePath;
454 
455                 customJsp = StringUtil.replace(
456                     customJsp, StringPool.DOUBLE_SLASH, StringPool.SLASH);
457 
458                 customJsps.add(customJsp);
459             }
460         }
461     }
462 
463     protected String getLocaleKey(String languagePropertiesLocation) {
464         String localeKey = null;
465 
466         int x = languagePropertiesLocation.indexOf(StringPool.UNDERLINE);
467         int y = languagePropertiesLocation.indexOf(".properties");
468 
469         if ((x != -1) && (y != 1)) {
470             localeKey = languagePropertiesLocation.substring(x + 1, y);
471         }
472 
473         return localeKey;
474     }
475 
476     protected BasePersistence getPersistence(String modelName) {
477         int pos = modelName.lastIndexOf(StringPool.PERIOD);
478 
479         String entityName = modelName.substring(pos + 1);
480 
481         pos = modelName.lastIndexOf(".model.");
482 
483         String packagePath = modelName.substring(0, pos);
484 
485         return (BasePersistence)PortalBeanLocatorUtil.locate(
486             packagePath + ".service.persistence." + entityName +
487                 "Persistence.impl");
488     }
489 
490     protected File getPortalJspBackupFile(File portalJspFile) {
491         String fileName = portalJspFile.toString();
492 
493         if (fileName.endsWith(".jsp")) {
494             fileName =
495                 fileName.substring(0, fileName.length() - 4) + ".portal.jsp";
496         }
497         else if (fileName.endsWith(".jspf")) {
498             fileName =
499                 fileName.substring(0, fileName.length() - 5) + ".portal.jspf";
500         }
501 
502         return new File(fileName);
503     }
504 
505     protected void initAutoLogins(
506             String servletContextName, ClassLoader portletClassLoader,
507             Properties portalProperties)
508         throws Exception {
509 
510         AutoLoginsContainer autoLoginsContainer = new AutoLoginsContainer();
511 
512         _autoLoginsContainerMap.put(servletContextName, autoLoginsContainer);
513 
514         String[] autoLoginClasses = StringUtil.split(
515             portalProperties.getProperty(AUTO_LOGIN_HOOKS));
516 
517         for (String autoLoginClass : autoLoginClasses) {
518             AutoLogin autoLogin = (AutoLogin)portletClassLoader.loadClass(
519                 autoLoginClass).newInstance();
520 
521             if (autoLogin != null) {
522                 autoLogin = new AutoLoginWrapper(autoLogin, portletClassLoader);
523 
524                 autoLoginsContainer.registerAutoLogin(autoLogin);
525             }
526         }
527     }
528 
529     protected void initCustomJspBag(CustomJspBag customJspBag)
530         throws Exception {
531 
532         String customJspDir = customJspBag.getCustomJspDir();
533         List<String> customJsps = customJspBag.getCustomJsps();
534         //String timestamp = customJspBag.getTimestamp();
535 
536         String portalWebDir = PortalUtil.getPortalWebDir();
537 
538         for (String customJsp : customJsps) {
539             int pos = customJsp.indexOf(customJspDir);
540 
541             String portalJsp = customJsp.substring(
542                 pos + customJspDir.length(), customJsp.length());
543 
544             File portalJspFile = new File(portalWebDir + portalJsp);
545             File portalJspBackupFile = getPortalJspBackupFile(portalJspFile);
546 
547             if (portalJspFile.exists() && !portalJspBackupFile.exists()) {
548                 FileUtil.copyFile(portalJspFile, portalJspBackupFile);
549             }
550 
551             String customJspContent = FileUtil.read(customJsp);
552 
553             FileUtil.write(portalJspFile, customJspContent);
554         }
555     }
556 
557     protected Object initEvent(
558             String eventName, String eventClass, ClassLoader portletClassLoader)
559         throws Exception {
560 
561         if (eventName.equals(APPLICATION_STARTUP_EVENTS)) {
562             SimpleAction simpleAction = new InvokerSimpleAction(
563                 (SimpleAction)portletClassLoader.loadClass(
564                     eventClass).newInstance());
565 
566             simpleAction = new SimpleActionWrapper(
567                 simpleAction, portletClassLoader);
568 
569             long companyId = CompanyThreadLocal.getCompanyId();
570 
571             long[] companyIds = PortalInstances.getCompanyIds();
572 
573             for (long curCompanyId : companyIds) {
574                 CompanyThreadLocal.setCompanyId(curCompanyId);
575 
576                 simpleAction.run(new String[] {String.valueOf(curCompanyId)});
577             }
578 
579             CompanyThreadLocal.setCompanyId(companyId);
580 
581             return null;
582         }
583 
584         if (ArrayUtil.contains(_PROPS_KEYS_EVENTS, eventName)) {
585             Action action = (Action)portletClassLoader.loadClass(
586                 eventClass).newInstance();
587 
588             action = new ActionWrapper(action, portletClassLoader);
589 
590             EventsProcessor.registerEvent(eventName, action);
591 
592             return action;
593         }
594 
595         return null;
596     }
597 
598     protected void initEvents(
599             String servletContextName, ClassLoader portletClassLoader,
600             Properties portalProperties)
601         throws Exception {
602 
603         EventsContainer eventsContainer = new EventsContainer();
604 
605         _eventsContainerMap.put(servletContextName, eventsContainer);
606 
607         Iterator<Object> itr = portalProperties.keySet().iterator();
608 
609         while (itr.hasNext()) {
610             String key = (String)itr.next();
611 
612             if (!key.equals(APPLICATION_STARTUP_EVENTS) &&
613                 !ArrayUtil.contains(_PROPS_KEYS_EVENTS, key)) {
614 
615                 continue;
616             }
617 
618             String eventName = key;
619             String[] eventClasses = StringUtil.split(
620                 portalProperties.getProperty(key));
621 
622             for (String eventClass : eventClasses) {
623                 Object obj = initEvent(
624                     eventName, eventClass, portletClassLoader);
625 
626                 if (obj == null) {
627                     continue;
628                 }
629 
630                 eventsContainer.registerEvent(eventName, obj);
631             }
632         }
633     }
634 
635     protected ModelListener initModelListener(
636             String modelName, String modelListenerClass,
637             ClassLoader portletClassLoader)
638         throws Exception {
639 
640         ModelListener modelListener =
641             (ModelListener)portletClassLoader.loadClass(
642                 modelListenerClass).newInstance();
643 
644         modelListener = new ModelListenerWrapper(
645             modelListener, portletClassLoader);
646 
647         BasePersistence persistence = getPersistence(modelName);
648 
649         persistence.registerListener(modelListener);
650 
651         return modelListener;
652     }
653 
654     protected void initModelListeners(
655             String servletContextName, ClassLoader portletClassLoader,
656             Properties portalProperties)
657         throws Exception {
658 
659         ModelListenersContainer modelListenersContainer =
660             new ModelListenersContainer();
661 
662         _modelListenersContainerMap.put(
663             servletContextName, modelListenersContainer);
664 
665         Iterator<Object> itr = portalProperties.keySet().iterator();
666 
667         while (itr.hasNext()) {
668             String key = (String)itr.next();
669 
670             if (!key.startsWith(VALUE_OBJECT_LISTENER)) {
671                 continue;
672             }
673 
674             String modelName = key.substring(VALUE_OBJECT_LISTENER.length());
675             String modelListenerClass = portalProperties.getProperty(key);
676 
677             ModelListener modelListener = initModelListener(
678                 modelName, modelListenerClass, portletClassLoader);
679 
680             if (modelListener != null) {
681                 modelListenersContainer.registerModelListener(
682                     modelName, modelListener);
683             }
684         }
685     }
686 
687     protected void initPortalProperties(Properties portalProperties)
688         throws Exception {
689 
690         PropsUtil.addProperties(portalProperties);
691 
692         if (_log.isDebugEnabled() && portalProperties.containsKey(LOCALES)) {
693             _log.debug(
694                 "Portlet locales " + portalProperties.getProperty(LOCALES));
695             _log.debug("Merged locales " + PropsUtil.get(LOCALES));
696             _log.debug(
697                 "Merged locales array length " +
698                     PropsUtil.getArray(LOCALES).length);
699         }
700 
701         resetPortalProperties(portalProperties);
702     }
703 
704     protected void resetPortalProperties(Properties portalProperties)
705         throws Exception {
706 
707         for (String fieldName : _PROPS_VALUES_BOOLEAN) {
708             String key = StringUtil.replace(
709                 fieldName.toLowerCase(), StringPool.UNDERLINE,
710                 StringPool.PERIOD);
711 
712             if (!containsKey(portalProperties, key)) {
713                 continue;
714             }
715 
716             try {
717                 Field field = PropsValues.class.getField(fieldName);
718 
719                 Boolean value = Boolean.valueOf(GetterUtil.getBoolean(
720                     PropsUtil.get(key)));
721 
722                 field.setBoolean(null, value);
723             }
724             catch (Exception e) {
725                 _log.error(
726                     "Error setting field " + fieldName + ": " + e.getMessage());
727             }
728         }
729 
730         for (String fieldName : _PROPS_VALUES_INTEGER) {
731             String key = StringUtil.replace(
732                 fieldName.toLowerCase(), StringPool.UNDERLINE,
733                 StringPool.PERIOD);
734 
735             if (!containsKey(portalProperties, key)) {
736                 continue;
737             }
738 
739             try {
740                 Field field = PropsValues.class.getField(fieldName);
741 
742                 Integer value = Integer.valueOf(GetterUtil.getInteger(
743                     PropsUtil.get(key)));
744 
745                 field.setInt(null, value);
746             }
747             catch (Exception e) {
748                 _log.error(
749                     "Error setting field " + fieldName + ": " + e.getMessage());
750             }
751         }
752 
753         for (String fieldName : _PROPS_VALUES_LONG) {
754             String key = StringUtil.replace(
755                 fieldName.toLowerCase(), StringPool.UNDERLINE,
756                 StringPool.PERIOD);
757 
758             if (!containsKey(portalProperties, key)) {
759                 continue;
760             }
761 
762             try {
763                 Field field = PropsValues.class.getField(fieldName);
764 
765                 Long value = Long.valueOf(GetterUtil.getLong(
766                     PropsUtil.get(key)));
767 
768                 field.setLong(null, value);
769             }
770             catch (Exception e) {
771                 _log.error(
772                     "Error setting field " + fieldName + ": " + e.getMessage());
773             }
774         }
775 
776         for (String fieldName : _PROPS_VALUES_STRING) {
777             String key = StringUtil.replace(
778                 fieldName.toLowerCase(), StringPool.UNDERLINE,
779                 StringPool.PERIOD);
780 
781             if (!containsKey(portalProperties, key)) {
782                 continue;
783             }
784 
785             try {
786                 Field field = PropsValues.class.getField(fieldName);
787 
788                 String value = GetterUtil.getString(PropsUtil.get(key));
789 
790                 field.set(null, value);
791             }
792             catch (Exception e) {
793                 _log.error(
794                     "Error setting field " + fieldName + ": " + e.getMessage());
795             }
796         }
797 
798         for (String fieldName : _PROPS_VALUES_STRING_ARRAY) {
799             String key = StringUtil.replace(
800                 fieldName.toLowerCase(), StringPool.UNDERLINE,
801                 StringPool.PERIOD);
802 
803             if (!containsKey(portalProperties, key)) {
804                 continue;
805             }
806 
807             try {
808                 Field field = PropsValues.class.getField(fieldName);
809 
810                 String[] value = PropsUtil.getArray(key);
811 
812                 field.set(null, value);
813             }
814             catch (Exception e) {
815                 _log.error(
816                     "Error setting field " + fieldName + ": " + e.getMessage());
817             }
818         }
819 
820         if (containsKey(portalProperties, LOCALES)) {
821             PropsValues.LOCALES = PropsUtil.getArray(LOCALES);
822 
823             LanguageUtil.init();
824         }
825 
826         CacheUtil.clearCache();
827     }
828 
829     private static final String[] _PROPS_KEYS_EVENTS = new String[] {
830         LOGIN_EVENTS_POST,
831         LOGIN_EVENTS_PRE,
832         LOGOUT_EVENTS_POST,
833         LOGOUT_EVENTS_PRE,
834         SERVLET_SERVICE_EVENTS_POST,
835         SERVLET_SERVICE_EVENTS_PRE
836     };
837 
838     private static final String[] _PROPS_VALUES_BOOLEAN = new String[] {
839         "AUTH_FORWARD_BY_LAST_PATH",
840         "JAVASCRIPT_FAST_LOAD",
841         "LAYOUT_TEMPLATE_CACHE_ENABLED",
842         "LAYOUT_USER_PRIVATE_LAYOUTS_AUTO_CREATE",
843         "LAYOUT_USER_PRIVATE_LAYOUTS_ENABLED",
844         "LAYOUT_USER_PRIVATE_LAYOUTS_MODIFIABLE",
845         "LAYOUT_USER_PUBLIC_LAYOUTS_AUTO_CREATE",
846         "LAYOUT_USER_PUBLIC_LAYOUTS_ENABLED",
847         "LAYOUT_USER_PUBLIC_LAYOUTS_MODIFIABLE",
848         "MY_PLACES_SHOW_COMMUNITY_PRIVATE_SITES_WITH_NO_LAYOUTS",
849         "MY_PLACES_SHOW_COMMUNITY_PUBLIC_SITES_WITH_NO_LAYOUTS",
850         "MY_PLACES_SHOW_ORGANIZATION_PRIVATE_SITES_WITH_NO_LAYOUTS",
851         "MY_PLACES_SHOW_ORGANIZATION_PUBLIC_SITES_WITH_NO_LAYOUTS",
852         "MY_PLACES_SHOW_USER_PRIVATE_SITES_WITH_NO_LAYOUTS",
853         "MY_PLACES_SHOW_USER_PUBLIC_SITES_WITH_NO_LAYOUTS",
854         "TERMS_OF_USE_REQUIRED",
855         "THEME_CSS_FAST_LOAD",
856         "THEME_IMAGES_FAST_LOAD"
857     };
858 
859     private static final String[] _PROPS_VALUES_INTEGER = new String[] {
860     };
861 
862     private static final String[] _PROPS_VALUES_LONG = new String[] {
863     };
864 
865     private static final String[] _PROPS_VALUES_STRING = new String[] {
866         "PASSWORDS_PASSWORDPOLICYTOOLKIT_GENERATOR",
867         "PASSWORDS_PASSWORDPOLICYTOOLKIT_STATIC"
868     };
869 
870     private static final String[] _PROPS_VALUES_STRING_ARRAY = new String[] {
871         "LAYOUT_STATIC_PORTLETS_ALL"
872     };
873 
874     private static Log _log =
875          LogFactoryUtil.getLog(HookHotDeployListener.class);
876 
877     private Map<String, AutoLoginsContainer> _autoLoginsContainerMap =
878         new HashMap<String, AutoLoginsContainer>();
879     private Map<String, CustomJspBag> _customJspBagsMap =
880         new HashMap<String, CustomJspBag>();
881     private Map<String, EventsContainer> _eventsContainerMap =
882         new HashMap<String, EventsContainer>();
883     private Map<String, LanguagesContainer> _languagesContainerMap =
884         new HashMap<String, LanguagesContainer>();
885     private Map<String, ModelListenersContainer> _modelListenersContainerMap =
886         new HashMap<String, ModelListenersContainer>();
887     private Map<String, Properties> _portalPropertiesMap =
888         new HashMap<String, Properties>();
889     private Set<String> _servletContextNames = new HashSet<String>();
890 
891     private class AutoLoginsContainer {
892 
893         public void registerAutoLogin(AutoLogin autoLogin) {
894             AutoLoginFilter.registerAutoLogin(autoLogin);
895 
896             _autoLogins.add(autoLogin);
897         }
898 
899         public void unregisterAutoLogins() {
900             for (AutoLogin autoLogin : _autoLogins) {
901                 AutoLoginFilter.unregisterAutoLogin(autoLogin);
902             }
903         }
904 
905         List<AutoLogin> _autoLogins = new ArrayList<AutoLogin>();
906 
907     }
908 
909     private class CustomJspBag {
910 
911         public CustomJspBag(String customJspDir, List<String> customJsps) {
912             _customJspDir = customJspDir;
913             _customJsps = customJsps;
914             _timestamp = Time.getTimestamp();
915         }
916 
917         public String getCustomJspDir() {
918             return _customJspDir;
919         }
920 
921         public List<String> getCustomJsps() {
922             return _customJsps;
923         }
924 
925         public String getTimestamp() {
926             return _timestamp;
927         }
928 
929         private String _customJspDir;
930         private List<String> _customJsps;
931         private String _timestamp;
932 
933     }
934 
935     private class EventsContainer {
936 
937         public void registerEvent(String eventName, Object event) {
938             List<Object> events = _eventsMap.get(eventName);
939 
940             if (events == null) {
941                 events = new ArrayList<Object>();
942 
943                 _eventsMap.put(eventName, events);
944             }
945 
946             events.add(event);
947         }
948 
949         public void unregisterEvents() {
950             for (Map.Entry<String, List<Object>> entry :
951                     _eventsMap.entrySet()) {
952 
953                 String eventName = entry.getKey();
954                 List<Object> events = entry.getValue();
955 
956                 for (Object event : events) {
957                     EventsProcessor.unregisterEvent(eventName, event);
958                 }
959             }
960         }
961 
962         private Map<String, List<Object>> _eventsMap =
963             new HashMap<String, List<Object>>();
964 
965     }
966 
967     private class LanguagesContainer {
968 
969         public void addLanguage(String localeKey, Properties properties) {
970             _multiMessageResources.putLocale(localeKey);
971 
972             Properties oldProperties = _multiMessageResources.putMessages(
973                 properties, localeKey);
974 
975             _languagesMap.put(localeKey, oldProperties);
976         }
977 
978         public void unregisterLanguages() {
979             for (String key : _languagesMap.keySet()) {
980                 Properties properties = _languagesMap.get(key);
981 
982                 _multiMessageResources.putMessages(properties, key);
983             }
984         }
985 
986         private MultiMessageResources _multiMessageResources =
987             MultiMessageResourcesFactory.getInstance();
988         private Map<String, Properties> _languagesMap =
989             new HashMap<String, Properties>();
990 
991     }
992 
993     private class ModelListenersContainer {
994 
995         public void registerModelListener(
996             String modelName, ModelListener modelListener) {
997 
998             List<ModelListener> modelListeners = _modelListenersMap.get(
999                 modelName);
1000
1001            if (modelListeners == null) {
1002                modelListeners = new ArrayList<ModelListener>();
1003
1004                _modelListenersMap.put(modelName, modelListeners);
1005            }
1006
1007            modelListeners.add(modelListener);
1008        }
1009
1010        public void unregisterModelListeners() {
1011            for (Map.Entry<String, List<ModelListener>> entry :
1012                    _modelListenersMap.entrySet()) {
1013
1014                String modelName = entry.getKey();
1015                List<ModelListener> modelListeners = entry.getValue();
1016
1017                BasePersistence persistence = getPersistence(modelName);
1018
1019                for (ModelListener modelListener : modelListeners) {
1020                    persistence.unregisterListener(modelListener);
1021                }
1022            }
1023        }
1024
1025        private Map<String, List<ModelListener>> _modelListenersMap =
1026            new HashMap<String, List<ModelListener>>();
1027
1028    }
1029
1030}