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 (Exception e) {
99              throwHotDeployException(event, "Error registering hook for ", e);
100         }
101     }
102 
103     public void invokeUndeploy(HotDeployEvent event) throws HotDeployException {
104         try {
105             doInvokeUndeploy(event);
106         }
107         catch (Exception e) {
108             throwHotDeployException(event, "Error unregistering hook for ", e);
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 + " registered " +
377                     "successfully. It is now ready to be used.");
378         }
379     }
380 
381     protected void doInvokeUndeploy(HotDeployEvent event) throws Exception {
382         ServletContext servletContext = event.getServletContext();
383 
384         String servletContextName = servletContext.getServletContextName();
385 
386         if (_log.isDebugEnabled()) {
387             _log.debug("Invoking undeploy for " + servletContextName);
388         }
389 
390         if (!_servletContextNames.remove(servletContextName)) {
391             return;
392         }
393 
394         AutoLoginsContainer autoLoginsContainer =
395             _autoLoginsContainerMap.remove(servletContextName);
396 
397         if (autoLoginsContainer != null) {
398             autoLoginsContainer.unregisterAutoLogins();
399         }
400 
401         CustomJspBag customJspBag = _customJspBagsMap.remove(
402             servletContextName);
403 
404         if (customJspBag != null) {
405             destroyCustomJspBag(customJspBag);
406         }
407 
408         EventsContainer eventsContainer = _eventsContainerMap.remove(
409             servletContextName);
410 
411         if (eventsContainer != null) {
412             eventsContainer.unregisterEvents();
413         }
414 
415         LanguagesContainer languagesContainer = _languagesContainerMap.remove(
416             servletContextName);
417 
418         if (languagesContainer != null) {
419             languagesContainer.unregisterLanguages();
420         }
421 
422         ModelListenersContainer modelListenersContainer =
423             _modelListenersContainerMap.remove(servletContextName);
424 
425         if (modelListenersContainer != null) {
426             modelListenersContainer.unregisterModelListeners();
427         }
428 
429         Properties portalProperties = _portalPropertiesMap.remove(
430             servletContextName);
431 
432         if (portalProperties != null) {
433             destroyPortalProperties(portalProperties);
434         }
435 
436         if (_log.isInfoEnabled()) {
437             _log.info(
438                 "Hook for " + servletContextName +
439                     " unregistered successfully");
440         }
441     }
442 
443     protected void getCustomJsps(
444         ServletContext servletContext, String webDir, String resourcePath,
445         List<String> customJsps) {
446 
447         Set<String> resourcePaths = servletContext.getResourcePaths(
448             resourcePath);
449 
450         for (String curResourcePath : resourcePaths) {
451             if (curResourcePath.endsWith(StringPool.SLASH)) {
452                 getCustomJsps(
453                     servletContext, webDir, curResourcePath, customJsps);
454             }
455             else {
456                 String customJsp = webDir + curResourcePath;
457 
458                 customJsp = StringUtil.replace(
459                     customJsp, StringPool.DOUBLE_SLASH, StringPool.SLASH);
460 
461                 customJsps.add(customJsp);
462             }
463         }
464     }
465 
466     protected String getLocaleKey(String languagePropertiesLocation) {
467         String localeKey = null;
468 
469         int x = languagePropertiesLocation.indexOf(StringPool.UNDERLINE);
470         int y = languagePropertiesLocation.indexOf(".properties");
471 
472         if ((x != -1) && (y != 1)) {
473             localeKey = languagePropertiesLocation.substring(x + 1, y);
474         }
475 
476         return localeKey;
477     }
478 
479     protected BasePersistence getPersistence(String modelName) {
480         int pos = modelName.lastIndexOf(StringPool.PERIOD);
481 
482         String entityName = modelName.substring(pos + 1);
483 
484         pos = modelName.lastIndexOf(".model.");
485 
486         String packagePath = modelName.substring(0, pos);
487 
488         return (BasePersistence)PortalBeanLocatorUtil.locate(
489             packagePath + ".service.persistence." + entityName +
490                 "Persistence.impl");
491     }
492 
493     protected File getPortalJspBackupFile(File portalJspFile) {
494         String fileName = portalJspFile.toString();
495 
496         if (fileName.endsWith(".jsp")) {
497             fileName =
498                 fileName.substring(0, fileName.length() - 4) + ".portal.jsp";
499         }
500         else if (fileName.endsWith(".jspf")) {
501             fileName =
502                 fileName.substring(0, fileName.length() - 5) + ".portal.jspf";
503         }
504 
505         return new File(fileName);
506     }
507 
508     protected void initAutoLogins(
509             String servletContextName, ClassLoader portletClassLoader,
510             Properties portalProperties)
511         throws Exception {
512 
513         AutoLoginsContainer autoLoginsContainer = new AutoLoginsContainer();
514 
515         _autoLoginsContainerMap.put(servletContextName, autoLoginsContainer);
516 
517         String[] autoLoginClasses = StringUtil.split(
518             portalProperties.getProperty(AUTO_LOGIN_HOOKS));
519 
520         for (String autoLoginClass : autoLoginClasses) {
521             AutoLogin autoLogin = (AutoLogin)portletClassLoader.loadClass(
522                 autoLoginClass).newInstance();
523 
524             if (autoLogin != null) {
525                 autoLogin = new AutoLoginWrapper(autoLogin, portletClassLoader);
526 
527                 autoLoginsContainer.registerAutoLogin(autoLogin);
528             }
529         }
530     }
531 
532     protected void initCustomJspBag(CustomJspBag customJspBag)
533         throws Exception {
534 
535         String customJspDir = customJspBag.getCustomJspDir();
536         List<String> customJsps = customJspBag.getCustomJsps();
537         //String timestamp = customJspBag.getTimestamp();
538 
539         String portalWebDir = PortalUtil.getPortalWebDir();
540 
541         for (String customJsp : customJsps) {
542             int pos = customJsp.indexOf(customJspDir);
543 
544             String portalJsp = customJsp.substring(
545                 pos + customJspDir.length(), customJsp.length());
546 
547             File portalJspFile = new File(portalWebDir + portalJsp);
548             File portalJspBackupFile = getPortalJspBackupFile(portalJspFile);
549 
550             if (portalJspFile.exists() && !portalJspBackupFile.exists()) {
551                 FileUtil.copyFile(portalJspFile, portalJspBackupFile);
552             }
553 
554             String customJspContent = FileUtil.read(customJsp);
555 
556             FileUtil.write(portalJspFile, customJspContent);
557         }
558     }
559 
560     protected Object initEvent(
561             String eventName, String eventClass, ClassLoader portletClassLoader)
562         throws Exception {
563 
564         if (eventName.equals(APPLICATION_STARTUP_EVENTS)) {
565             SimpleAction simpleAction = new InvokerSimpleAction(
566                 (SimpleAction)portletClassLoader.loadClass(
567                     eventClass).newInstance());
568 
569             simpleAction = new SimpleActionWrapper(
570                 simpleAction, portletClassLoader);
571 
572             long companyId = CompanyThreadLocal.getCompanyId();
573 
574             long[] companyIds = PortalInstances.getCompanyIds();
575 
576             for (long curCompanyId : companyIds) {
577                 CompanyThreadLocal.setCompanyId(curCompanyId);
578 
579                 simpleAction.run(new String[] {String.valueOf(curCompanyId)});
580             }
581 
582             CompanyThreadLocal.setCompanyId(companyId);
583 
584             return null;
585         }
586 
587         if (ArrayUtil.contains(_PROPS_KEYS_EVENTS, eventName)) {
588             Action action = (Action)portletClassLoader.loadClass(
589                 eventClass).newInstance();
590 
591             action = new ActionWrapper(action, portletClassLoader);
592 
593             EventsProcessor.registerEvent(eventName, action);
594 
595             return action;
596         }
597 
598         return null;
599     }
600 
601     protected void initEvents(
602             String servletContextName, ClassLoader portletClassLoader,
603             Properties portalProperties)
604         throws Exception {
605 
606         EventsContainer eventsContainer = new EventsContainer();
607 
608         _eventsContainerMap.put(servletContextName, eventsContainer);
609 
610         Iterator<Object> itr = portalProperties.keySet().iterator();
611 
612         while (itr.hasNext()) {
613             String key = (String)itr.next();
614 
615             if (!key.equals(APPLICATION_STARTUP_EVENTS) &&
616                 !ArrayUtil.contains(_PROPS_KEYS_EVENTS, key)) {
617 
618                 continue;
619             }
620 
621             String eventName = key;
622             String[] eventClasses = StringUtil.split(
623                 portalProperties.getProperty(key));
624 
625             for (String eventClass : eventClasses) {
626                 Object obj = initEvent(
627                     eventName, eventClass, portletClassLoader);
628 
629                 if (obj == null) {
630                     continue;
631                 }
632 
633                 eventsContainer.registerEvent(eventName, obj);
634             }
635         }
636     }
637 
638     protected ModelListener initModelListener(
639             String modelName, String modelListenerClass,
640             ClassLoader portletClassLoader)
641         throws Exception {
642 
643         ModelListener modelListener =
644             (ModelListener)portletClassLoader.loadClass(
645                 modelListenerClass).newInstance();
646 
647         modelListener = new ModelListenerWrapper(
648             modelListener, portletClassLoader);
649 
650         BasePersistence persistence = getPersistence(modelName);
651 
652         persistence.registerListener(modelListener);
653 
654         return modelListener;
655     }
656 
657     protected void initModelListeners(
658             String servletContextName, ClassLoader portletClassLoader,
659             Properties portalProperties)
660         throws Exception {
661 
662         ModelListenersContainer modelListenersContainer =
663             new ModelListenersContainer();
664 
665         _modelListenersContainerMap.put(
666             servletContextName, modelListenersContainer);
667 
668         Iterator<Object> itr = portalProperties.keySet().iterator();
669 
670         while (itr.hasNext()) {
671             String key = (String)itr.next();
672 
673             if (!key.startsWith(VALUE_OBJECT_LISTENER)) {
674                 continue;
675             }
676 
677             String modelName = key.substring(VALUE_OBJECT_LISTENER.length());
678             String modelListenerClass = portalProperties.getProperty(key);
679 
680             ModelListener modelListener = initModelListener(
681                 modelName, modelListenerClass, portletClassLoader);
682 
683             if (modelListener != null) {
684                 modelListenersContainer.registerModelListener(
685                     modelName, modelListener);
686             }
687         }
688     }
689 
690     protected void initPortalProperties(Properties portalProperties)
691         throws Exception {
692 
693         PropsUtil.addProperties(portalProperties);
694 
695         if (_log.isDebugEnabled() && portalProperties.containsKey(LOCALES)) {
696             _log.debug(
697                 "Portlet locales " + portalProperties.getProperty(LOCALES));
698             _log.debug("Merged locales " + PropsUtil.get(LOCALES));
699             _log.debug(
700                 "Merged locales array length " +
701                     PropsUtil.getArray(LOCALES).length);
702         }
703 
704         resetPortalProperties(portalProperties);
705     }
706 
707     protected void resetPortalProperties(Properties portalProperties)
708         throws Exception {
709 
710         for (String fieldName : _PROPS_VALUES_BOOLEAN) {
711             String key = StringUtil.replace(
712                 fieldName.toLowerCase(), StringPool.UNDERLINE,
713                 StringPool.PERIOD);
714 
715             if (!containsKey(portalProperties, key)) {
716                 continue;
717             }
718 
719             try {
720                 Field field = PropsValues.class.getField(fieldName);
721 
722                 Boolean value = Boolean.valueOf(GetterUtil.getBoolean(
723                     PropsUtil.get(key)));
724 
725                 field.setBoolean(null, value);
726             }
727             catch (Exception e) {
728                 _log.error(
729                     "Error setting field " + fieldName + ": " + e.getMessage());
730             }
731         }
732 
733         for (String fieldName : _PROPS_VALUES_INTEGER) {
734             String key = StringUtil.replace(
735                 fieldName.toLowerCase(), StringPool.UNDERLINE,
736                 StringPool.PERIOD);
737 
738             if (!containsKey(portalProperties, key)) {
739                 continue;
740             }
741 
742             try {
743                 Field field = PropsValues.class.getField(fieldName);
744 
745                 Integer value = Integer.valueOf(GetterUtil.getInteger(
746                     PropsUtil.get(key)));
747 
748                 field.setInt(null, value);
749             }
750             catch (Exception e) {
751                 _log.error(
752                     "Error setting field " + fieldName + ": " + e.getMessage());
753             }
754         }
755 
756         for (String fieldName : _PROPS_VALUES_LONG) {
757             String key = StringUtil.replace(
758                 fieldName.toLowerCase(), StringPool.UNDERLINE,
759                 StringPool.PERIOD);
760 
761             if (!containsKey(portalProperties, key)) {
762                 continue;
763             }
764 
765             try {
766                 Field field = PropsValues.class.getField(fieldName);
767 
768                 Long value = Long.valueOf(GetterUtil.getLong(
769                     PropsUtil.get(key)));
770 
771                 field.setLong(null, value);
772             }
773             catch (Exception e) {
774                 _log.error(
775                     "Error setting field " + fieldName + ": " + e.getMessage());
776             }
777         }
778 
779         for (String fieldName : _PROPS_VALUES_STRING) {
780             String key = StringUtil.replace(
781                 fieldName.toLowerCase(), StringPool.UNDERLINE,
782                 StringPool.PERIOD);
783 
784             if (!containsKey(portalProperties, key)) {
785                 continue;
786             }
787 
788             try {
789                 Field field = PropsValues.class.getField(fieldName);
790 
791                 String value = GetterUtil.getString(PropsUtil.get(key));
792 
793                 field.set(null, value);
794             }
795             catch (Exception e) {
796                 _log.error(
797                     "Error setting field " + fieldName + ": " + e.getMessage());
798             }
799         }
800 
801         for (String fieldName : _PROPS_VALUES_STRING_ARRAY) {
802             String key = StringUtil.replace(
803                 fieldName.toLowerCase(), StringPool.UNDERLINE,
804                 StringPool.PERIOD);
805 
806             if (!containsKey(portalProperties, key)) {
807                 continue;
808             }
809 
810             try {
811                 Field field = PropsValues.class.getField(fieldName);
812 
813                 String[] value = PropsUtil.getArray(key);
814 
815                 field.set(null, value);
816             }
817             catch (Exception e) {
818                 _log.error(
819                     "Error setting field " + fieldName + ": " + e.getMessage());
820             }
821         }
822 
823         if (containsKey(portalProperties, LOCALES)) {
824             PropsValues.LOCALES = PropsUtil.getArray(LOCALES);
825 
826             LanguageUtil.init();
827         }
828 
829         CacheUtil.clearCache();
830     }
831 
832     private static final String[] _PROPS_KEYS_EVENTS = new String[] {
833         LOGIN_EVENTS_POST,
834         LOGIN_EVENTS_PRE,
835         LOGOUT_EVENTS_POST,
836         LOGOUT_EVENTS_PRE,
837         SERVLET_SERVICE_EVENTS_POST,
838         SERVLET_SERVICE_EVENTS_PRE
839     };
840 
841     private static final String[] _PROPS_VALUES_BOOLEAN = new String[] {
842         "AUTH_FORWARD_BY_LAST_PATH",
843         "JAVASCRIPT_FAST_LOAD",
844         "LAYOUT_TEMPLATE_CACHE_ENABLED",
845         "LAYOUT_USER_PRIVATE_LAYOUTS_AUTO_CREATE",
846         "LAYOUT_USER_PRIVATE_LAYOUTS_ENABLED",
847         "LAYOUT_USER_PRIVATE_LAYOUTS_MODIFIABLE",
848         "LAYOUT_USER_PUBLIC_LAYOUTS_AUTO_CREATE",
849         "LAYOUT_USER_PUBLIC_LAYOUTS_ENABLED",
850         "LAYOUT_USER_PUBLIC_LAYOUTS_MODIFIABLE",
851         "MY_PLACES_SHOW_COMMUNITY_PRIVATE_SITES_WITH_NO_LAYOUTS",
852         "MY_PLACES_SHOW_COMMUNITY_PUBLIC_SITES_WITH_NO_LAYOUTS",
853         "MY_PLACES_SHOW_ORGANIZATION_PRIVATE_SITES_WITH_NO_LAYOUTS",
854         "MY_PLACES_SHOW_ORGANIZATION_PUBLIC_SITES_WITH_NO_LAYOUTS",
855         "MY_PLACES_SHOW_USER_PRIVATE_SITES_WITH_NO_LAYOUTS",
856         "MY_PLACES_SHOW_USER_PUBLIC_SITES_WITH_NO_LAYOUTS",
857         "TERMS_OF_USE_REQUIRED",
858         "THEME_CSS_FAST_LOAD",
859         "THEME_IMAGES_FAST_LOAD"
860     };
861 
862     private static final String[] _PROPS_VALUES_INTEGER = new String[] {
863     };
864 
865     private static final String[] _PROPS_VALUES_LONG = new String[] {
866     };
867 
868     private static final String[] _PROPS_VALUES_STRING = new String[] {
869         "PASSWORDS_PASSWORDPOLICYTOOLKIT_GENERATOR",
870         "PASSWORDS_PASSWORDPOLICYTOOLKIT_STATIC"
871     };
872 
873     private static final String[] _PROPS_VALUES_STRING_ARRAY = new String[] {
874         "LAYOUT_STATIC_PORTLETS_ALL"
875     };
876 
877     private static Log _log =
878          LogFactoryUtil.getLog(HookHotDeployListener.class);
879 
880     private Map<String, AutoLoginsContainer> _autoLoginsContainerMap =
881         new HashMap<String, AutoLoginsContainer>();
882     private Map<String, CustomJspBag> _customJspBagsMap =
883         new HashMap<String, CustomJspBag>();
884     private Map<String, EventsContainer> _eventsContainerMap =
885         new HashMap<String, EventsContainer>();
886     private Map<String, LanguagesContainer> _languagesContainerMap =
887         new HashMap<String, LanguagesContainer>();
888     private Map<String, ModelListenersContainer> _modelListenersContainerMap =
889         new HashMap<String, ModelListenersContainer>();
890     private Map<String, Properties> _portalPropertiesMap =
891         new HashMap<String, Properties>();
892     private Set<String> _servletContextNames = new HashSet<String>();
893 
894     private class AutoLoginsContainer {
895 
896         public void registerAutoLogin(AutoLogin autoLogin) {
897             AutoLoginFilter.registerAutoLogin(autoLogin);
898 
899             _autoLogins.add(autoLogin);
900         }
901 
902         public void unregisterAutoLogins() {
903             for (AutoLogin autoLogin : _autoLogins) {
904                 AutoLoginFilter.unregisterAutoLogin(autoLogin);
905             }
906         }
907 
908         List<AutoLogin> _autoLogins = new ArrayList<AutoLogin>();
909 
910     }
911 
912     private class CustomJspBag {
913 
914         public CustomJspBag(String customJspDir, List<String> customJsps) {
915             _customJspDir = customJspDir;
916             _customJsps = customJsps;
917             _timestamp = Time.getTimestamp();
918         }
919 
920         public String getCustomJspDir() {
921             return _customJspDir;
922         }
923 
924         public List<String> getCustomJsps() {
925             return _customJsps;
926         }
927 
928         public String getTimestamp() {
929             return _timestamp;
930         }
931 
932         private String _customJspDir;
933         private List<String> _customJsps;
934         private String _timestamp;
935 
936     }
937 
938     private class EventsContainer {
939 
940         public void registerEvent(String eventName, Object event) {
941             List<Object> events = _eventsMap.get(eventName);
942 
943             if (events == null) {
944                 events = new ArrayList<Object>();
945 
946                 _eventsMap.put(eventName, events);
947             }
948 
949             events.add(event);
950         }
951 
952         public void unregisterEvents() {
953             for (Map.Entry<String, List<Object>> entry :
954                     _eventsMap.entrySet()) {
955 
956                 String eventName = entry.getKey();
957                 List<Object> events = entry.getValue();
958 
959                 for (Object event : events) {
960                     EventsProcessor.unregisterEvent(eventName, event);
961                 }
962             }
963         }
964 
965         private Map<String, List<Object>> _eventsMap =
966             new HashMap<String, List<Object>>();
967 
968     }
969 
970     private class LanguagesContainer {
971 
972         public void addLanguage(String localeKey, Properties properties) {
973             _multiMessageResources.putLocale(localeKey);
974 
975             Properties oldProperties = _multiMessageResources.putMessages(
976                 properties, localeKey);
977 
978             _languagesMap.put(localeKey, oldProperties);
979         }
980 
981         public void unregisterLanguages() {
982             for (String key : _languagesMap.keySet()) {
983                 Properties properties = _languagesMap.get(key);
984 
985                 _multiMessageResources.putMessages(properties, key);
986             }
987         }
988 
989         private MultiMessageResources _multiMessageResources =
990             MultiMessageResourcesFactory.getInstance();
991         private Map<String, Properties> _languagesMap =
992             new HashMap<String, Properties>();
993 
994     }
995 
996     private class ModelListenersContainer {
997 
998         public void registerModelListener(
999             String modelName, ModelListener modelListener) {
1000
1001            List<ModelListener> modelListeners = _modelListenersMap.get(
1002                modelName);
1003
1004            if (modelListeners == null) {
1005                modelListeners = new ArrayList<ModelListener>();
1006
1007                _modelListenersMap.put(modelName, modelListeners);
1008            }
1009
1010            modelListeners.add(modelListener);
1011        }
1012
1013        public void unregisterModelListeners() {
1014            for (Map.Entry<String, List<ModelListener>> entry :
1015                    _modelListenersMap.entrySet()) {
1016
1017                String modelName = entry.getKey();
1018                List<ModelListener> modelListeners = entry.getValue();
1019
1020                BasePersistence persistence = getPersistence(modelName);
1021
1022                for (ModelListener modelListener : modelListeners) {
1023                    persistence.unregisterListener(modelListener);
1024                }
1025            }
1026        }
1027
1028        private Map<String, List<ModelListener>> _modelListenersMap =
1029            new HashMap<String, List<ModelListener>>();
1030
1031    }
1032
1033}