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