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