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