1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.deploy.hot;
16  
17  import com.liferay.portal.events.EventsProcessorUtil;
18  import com.liferay.portal.kernel.bean.ContextClassLoaderBeanHandler;
19  import com.liferay.portal.kernel.bean.PortalBeanLocatorUtil;
20  import com.liferay.portal.kernel.configuration.Configuration;
21  import com.liferay.portal.kernel.configuration.ConfigurationFactoryUtil;
22  import com.liferay.portal.kernel.deploy.auto.AutoDeployDir;
23  import com.liferay.portal.kernel.deploy.auto.AutoDeployListener;
24  import com.liferay.portal.kernel.deploy.auto.AutoDeployUtil;
25  import com.liferay.portal.kernel.deploy.hot.BaseHotDeployListener;
26  import com.liferay.portal.kernel.deploy.hot.HotDeployEvent;
27  import com.liferay.portal.kernel.deploy.hot.HotDeployException;
28  import com.liferay.portal.kernel.deploy.hot.HotDeployListener;
29  import com.liferay.portal.kernel.deploy.hot.HotDeployUtil;
30  import com.liferay.portal.kernel.events.Action;
31  import com.liferay.portal.kernel.events.InvokerAction;
32  import com.liferay.portal.kernel.events.InvokerSessionAction;
33  import com.liferay.portal.kernel.events.InvokerSimpleAction;
34  import com.liferay.portal.kernel.events.SessionAction;
35  import com.liferay.portal.kernel.events.SimpleAction;
36  import com.liferay.portal.kernel.exception.PortalException;
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.upgrade.UpgradeException;
41  import com.liferay.portal.kernel.util.ArrayUtil;
42  import com.liferay.portal.kernel.util.FileUtil;
43  import com.liferay.portal.kernel.util.GetterUtil;
44  import com.liferay.portal.kernel.util.HttpUtil;
45  import com.liferay.portal.kernel.util.ListUtil;
46  import com.liferay.portal.kernel.util.LocaleUtil;
47  import com.liferay.portal.kernel.util.PropsKeys;
48  import com.liferay.portal.kernel.util.StringBundler;
49  import com.liferay.portal.kernel.util.StringPool;
50  import com.liferay.portal.kernel.util.StringUtil;
51  import com.liferay.portal.kernel.util.Validator;
52  import com.liferay.portal.kernel.xml.Document;
53  import com.liferay.portal.kernel.xml.Element;
54  import com.liferay.portal.kernel.xml.SAXReaderUtil;
55  import com.liferay.portal.language.LanguageResources;
56  import com.liferay.portal.model.BaseModel;
57  import com.liferay.portal.model.ModelListener;
58  import com.liferay.portal.model.Release;
59  import com.liferay.portal.security.auth.AuthFailure;
60  import com.liferay.portal.security.auth.AuthPipeline;
61  import com.liferay.portal.security.auth.Authenticator;
62  import com.liferay.portal.security.auth.AutoLogin;
63  import com.liferay.portal.security.auth.CompanyThreadLocal;
64  import com.liferay.portal.security.auth.EmailAddressGenerator;
65  import com.liferay.portal.security.auth.EmailAddressGeneratorFactory;
66  import com.liferay.portal.security.auth.FullNameValidator;
67  import com.liferay.portal.security.auth.FullNameValidatorFactory;
68  import com.liferay.portal.security.auth.ScreenNameGenerator;
69  import com.liferay.portal.security.auth.ScreenNameGeneratorFactory;
70  import com.liferay.portal.security.auth.ScreenNameValidator;
71  import com.liferay.portal.security.auth.ScreenNameValidatorFactory;
72  import com.liferay.portal.security.ldap.AttributesTransformer;
73  import com.liferay.portal.security.ldap.AttributesTransformerFactory;
74  import com.liferay.portal.service.ReleaseLocalServiceUtil;
75  import com.liferay.portal.service.persistence.BasePersistence;
76  import com.liferay.portal.servlet.filters.autologin.AutoLoginFilter;
77  import com.liferay.portal.servlet.filters.cache.CacheUtil;
78  import com.liferay.portal.spring.aop.ServiceHookAdvice;
79  import com.liferay.portal.struts.MultiMessageResources;
80  import com.liferay.portal.struts.MultiMessageResourcesFactory;
81  import com.liferay.portal.upgrade.UpgradeProcessUtil;
82  import com.liferay.portal.util.PortalInstances;
83  import com.liferay.portal.util.PortalUtil;
84  import com.liferay.portal.util.PropsUtil;
85  import com.liferay.portal.util.PropsValues;
86  import com.liferay.portlet.ControlPanelEntry;
87  import com.liferay.portlet.DefaultControlPanelEntryFactory;
88  import com.liferay.util.UniqueList;
89  
90  import java.io.File;
91  import java.io.InputStream;
92  
93  import java.lang.reflect.Constructor;
94  import java.lang.reflect.Field;
95  import java.lang.reflect.Proxy;
96  
97  import java.net.URL;
98  
99  import java.util.ArrayList;
100 import java.util.HashMap;
101 import java.util.HashSet;
102 import java.util.Iterator;
103 import java.util.List;
104 import java.util.Locale;
105 import java.util.Map;
106 import java.util.Properties;
107 import java.util.Set;
108 
109 import javax.servlet.ServletContext;
110 
111 /**
112  * <a href="HookHotDeployListener.java.html"><b><i>View Source</i></b></a>
113  *
114  * @author Brian Wing Shun Chan
115  * @author Bruno Farache
116  * @author Wesley Gong
117  */
118 public class HookHotDeployListener
119     extends BaseHotDeployListener implements PropsKeys {
120 
121     public HookHotDeployListener() {
122         for (String key : _PROPS_VALUES_STRING_ARRAY) {
123             _stringArraysContainerMap.put(key, new StringArraysContainer(key));
124         }
125     }
126 
127     public void invokeDeploy(HotDeployEvent event) throws HotDeployException {
128         try {
129             doInvokeDeploy(event);
130         }
131         catch (Throwable t) {
132             throwHotDeployException(event, "Error registering hook for ", t);
133         }
134     }
135 
136     public void invokeUndeploy(HotDeployEvent event) throws HotDeployException {
137         try {
138             doInvokeUndeploy(event);
139         }
140         catch (Throwable t) {
141             throwHotDeployException(event, "Error unregistering hook for ", t);
142         }
143     }
144 
145     protected boolean containsKey(Properties portalProperties, String key) {
146         if (_log.isDebugEnabled()) {
147             return true;
148         }
149         else {
150             return portalProperties.containsKey(key);
151         }
152     }
153 
154     protected void destroyCustomJspBag(CustomJspBag customJspBag) {
155         String customJspDir = customJspBag.getCustomJspDir();
156         List<String> customJsps = customJspBag.getCustomJsps();
157         //String timestamp = customJspBag.getTimestamp();
158 
159         String portalWebDir = PortalUtil.getPortalWebDir();
160 
161         for (String customJsp : customJsps) {
162             int pos = customJsp.indexOf(customJspDir);
163 
164             String portalJsp = customJsp.substring(
165                 pos + customJspDir.length(), customJsp.length());
166 
167             File portalJspFile = new File(portalWebDir + portalJsp);
168             File portalJspBackupFile = getPortalJspBackupFile(portalJspFile);
169 
170             if (portalJspBackupFile.exists()) {
171                 FileUtil.copyFile(portalJspBackupFile, portalJspFile);
172 
173                 portalJspBackupFile.delete();
174             }
175             else if (portalJspFile.exists()) {
176                 portalJspFile.delete();
177             }
178         }
179     }
180 
181     protected void destroyPortalProperties(
182             String servletContextName, Properties portalProperties)
183         throws Exception {
184 
185         PropsUtil.removeProperties(portalProperties);
186 
187         if (_log.isDebugEnabled() && portalProperties.containsKey(LOCALES)) {
188             _log.debug(
189                 "Portlet locales " + portalProperties.getProperty(LOCALES));
190             _log.debug("Original locales " + PropsUtil.get(LOCALES));
191             _log.debug(
192                 "Original locales array length " +
193                     PropsUtil.getArray(LOCALES).length);
194         }
195 
196         resetPortalProperties(servletContextName, portalProperties, false);
197 
198         if (portalProperties.containsKey(
199                 PropsKeys.CONTROL_PANEL_DEFAULT_ENTRY_CLASS)) {
200 
201             DefaultControlPanelEntryFactory.setInstance(null);
202         }
203 
204         if (portalProperties.containsKey(PropsKeys.DL_HOOK_IMPL)) {
205             com.liferay.documentlibrary.util.HookFactory.setInstance(null);
206         }
207 
208         if (portalProperties.containsKey(PropsKeys.IMAGE_HOOK_IMPL)) {
209             com.liferay.portal.image.HookFactory.setInstance(null);
210         }
211 
212         if (portalProperties.containsKey(
213                 PropsKeys.LDAP_ATTRS_TRANSFORMER_IMPL)) {
214 
215             AttributesTransformerFactory.setInstance(null);
216         }
217 
218         if (portalProperties.containsKey(PropsKeys.MAIL_HOOK_IMPL)) {
219             com.liferay.mail.util.HookFactory.setInstance(null);
220         }
221 
222         if (portalProperties.containsKey(
223                 PropsKeys.USERS_EMAIL_ADDRESS_GENERATOR)) {
224 
225             EmailAddressGeneratorFactory.setInstance(null);
226         }
227 
228         if (portalProperties.containsKey(PropsKeys.USERS_FULL_NAME_VALIDATOR)) {
229             FullNameValidatorFactory.setInstance(null);
230         }
231 
232         if (portalProperties.containsKey(
233                 PropsKeys.USERS_SCREEN_NAME_GENERATOR)) {
234 
235             ScreenNameGeneratorFactory.setInstance(null);
236         }
237 
238         if (portalProperties.containsKey(
239                 PropsKeys.USERS_SCREEN_NAME_VALIDATOR)) {
240 
241             ScreenNameValidatorFactory.setInstance(null);
242         }
243     }
244 
245     protected void doInvokeDeploy(HotDeployEvent event) throws Exception {
246         ServletContext servletContext = event.getServletContext();
247 
248         String servletContextName = servletContext.getServletContextName();
249 
250         if (_log.isDebugEnabled()) {
251             _log.debug("Invoking deploy for " + servletContextName);
252         }
253 
254         String xml = HttpUtil.URLtoString(
255             servletContext.getResource("/WEB-INF/liferay-hook.xml"));
256 
257         if (xml == null) {
258             return;
259         }
260 
261         if (_log.isInfoEnabled()) {
262             _log.info("Registering hook for " + servletContextName);
263         }
264 
265         _servletContextNames.add(servletContextName);
266 
267         ClassLoader portletClassLoader = event.getContextClassLoader();
268 
269         Document doc = SAXReaderUtil.read(xml, true);
270 
271         Element root = doc.getRootElement();
272 
273         String portalPropertiesLocation = root.elementText("portal-properties");
274 
275         if (Validator.isNotNull(portalPropertiesLocation)) {
276             Configuration portalPropertiesConfiguration = null;
277 
278             try {
279                 String name = portalPropertiesLocation;
280 
281                 int pos = name.lastIndexOf(".properties");
282 
283                 if (pos != -1) {
284                     name = name.substring(0, pos);
285                 }
286 
287                 portalPropertiesConfiguration =
288                     ConfigurationFactoryUtil.getConfiguration(
289                         portletClassLoader, name);
290             }
291             catch (Exception e) {
292                 _log.error("Unable to read " + portalPropertiesLocation, e);
293             }
294 
295             if (portalPropertiesConfiguration != null) {
296                 Properties portalProperties =
297                     portalPropertiesConfiguration.getProperties();
298 
299                 if (portalProperties.size() > 0) {
300                     _portalPropertiesMap.put(
301                         servletContextName, portalProperties);
302 
303                     // Initialize properties, auto logins, model listeners, and
304                     // events in that specific order. Events have to be loaded
305                     // last because they may require model listeners to have
306                     // been registered.
307 
308                     initPortalProperties(
309                         servletContextName, portletClassLoader,
310                         portalProperties);
311                     initAuthFailures(
312                         servletContextName, portletClassLoader,
313                         portalProperties);
314                     initAutoDeployListeners(
315                         servletContextName, portletClassLoader,
316                         portalProperties);
317                     initAutoLogins(
318                         servletContextName, portletClassLoader,
319                         portalProperties);
320                     initHotDeployListeners(
321                         servletContextName, portletClassLoader,
322                         portalProperties);
323                     initModelListeners(
324                         servletContextName, portletClassLoader,
325                         portalProperties);
326                     initEvents(
327                         servletContextName, portletClassLoader,
328                         portalProperties);
329                 }
330             }
331         }
332 
333         LanguagesContainer languagesContainer = new LanguagesContainer();
334 
335         _languagesContainerMap.put(servletContextName, languagesContainer);
336 
337         List<Element> languagePropertiesEls = root.elements(
338             "language-properties");
339 
340         for (Element languagePropertiesEl : languagePropertiesEls) {
341             String languagePropertiesLocation = languagePropertiesEl.getText();
342 
343             try {
344                 URL url = portletClassLoader.getResource(
345                     languagePropertiesLocation);
346 
347                 if (url == null) {
348                     continue;
349                 }
350 
351                 InputStream is = url.openStream();
352 
353                 Properties properties = new Properties();
354 
355                 properties.load(is);
356 
357                 is.close();
358 
359                 String localeKey = getLocaleKey(languagePropertiesLocation);
360 
361                 if (localeKey != null) {
362                     languagesContainer.addLanguage(localeKey, properties);
363                 }
364             }
365             catch (Exception e) {
366                 _log.error("Unable to read " + languagePropertiesLocation, e);
367             }
368         }
369 
370         String customJspDir = root.elementText("custom-jsp-dir");
371 
372         if (Validator.isNotNull(customJspDir)) {
373             if (_log.isDebugEnabled()) {
374                 _log.debug("Custom JSP directory: " + customJspDir);
375             }
376 
377             List<String> customJsps = new ArrayList<String>();
378 
379             String webDir = servletContext.getRealPath(StringPool.SLASH);
380 
381             getCustomJsps(servletContext, webDir, customJspDir, customJsps);
382 
383             if (customJsps.size() > 0) {
384                 CustomJspBag customJspBag = new CustomJspBag(
385                     customJspDir, customJsps);
386 
387                 if (_log.isDebugEnabled()) {
388                     StringBundler sb = new StringBundler(customJsps.size() * 2);
389 
390                     sb.append("Custom JSP files:\n");
391 
392                     Iterator<String> itr = customJsps.iterator();
393 
394                     while (itr.hasNext()) {
395                         String customJsp = itr.next();
396 
397                         sb.append(customJsp);
398 
399                         if (itr.hasNext()) {
400                             sb.append(StringPool.NEW_LINE);
401                         }
402                     }
403 
404                     _log.debug(sb.toString());
405                 }
406 
407                 _customJspBagsMap.put(servletContextName, customJspBag);
408 
409                 initCustomJspBag(customJspBag);
410             }
411         }
412 
413         ServicesContainer servicesContainer = new ServicesContainer();
414 
415         _servicesContainerMap.put(servletContextName, servicesContainer);
416 
417         List<Element> serviceEls = root.elements("service");
418 
419         for (Element serviceEl : serviceEls) {
420             String serviceType = serviceEl.elementText("service-type");
421             String serviceImpl = serviceEl.elementText("service-impl");
422 
423             Class<?> serviceTypeClass = portletClassLoader.loadClass(
424                 serviceType);
425             Class<?> serviceImplClass = portletClassLoader.loadClass(
426                 serviceImpl);
427 
428             Constructor<?> serviceImplConstructor =
429                 serviceImplClass.getConstructor(new Class[] {serviceTypeClass});
430 
431             Object serviceImplInstance = serviceImplConstructor.newInstance(
432                 PortalBeanLocatorUtil.locate(serviceType));
433 
434             serviceImplInstance = Proxy.newProxyInstance(
435                 portletClassLoader, new Class[] {serviceTypeClass},
436                 new ContextClassLoaderBeanHandler(
437                     serviceImplInstance, portletClassLoader));
438 
439             servicesContainer.addService(serviceType, serviceImplInstance);
440         }
441 
442         // Begin backwards compatibility for 5.1.0
443 
444         ModelListenersContainer modelListenersContainer =
445             _modelListenersContainerMap.get(servletContextName);
446 
447         if (modelListenersContainer == null) {
448             modelListenersContainer = new ModelListenersContainer();
449 
450             _modelListenersContainerMap.put(
451                 servletContextName, modelListenersContainer);
452         }
453 
454         List<Element> modelListenerEls = root.elements("model-listener");
455 
456         for (Element modelListenerEl : modelListenerEls) {
457             String modelName = modelListenerEl.elementText("model-name");
458             String modelListenerClassName = modelListenerEl.elementText(
459                 "model-listener-class");
460 
461             ModelListener<BaseModel<?>> modelListener = initModelListener(
462                 modelName, modelListenerClassName, portletClassLoader);
463 
464             if (modelListener != null) {
465                 modelListenersContainer.registerModelListener(
466                     modelName, modelListener);
467             }
468         }
469 
470         EventsContainer eventsContainer = _eventsContainerMap.get(
471             servletContextName);
472 
473         if (eventsContainer == null) {
474             eventsContainer = new EventsContainer();
475 
476             _eventsContainerMap.put(servletContextName, eventsContainer);
477         }
478 
479         List<Element> eventEls = root.elements("event");
480 
481         for (Element eventEl : eventEls) {
482             String eventName = eventEl.elementText("event-type");
483             String eventClassName = eventEl.elementText("event-class");
484 
485             Object obj = initEvent(
486                 eventName, eventClassName, portletClassLoader);
487 
488             if (obj != null) {
489                 eventsContainer.registerEvent(eventName, obj);
490             }
491         }
492 
493         // End backwards compatibility for 5.1.0
494 
495         registerClpMessageListeners(servletContext, portletClassLoader);
496 
497         if (_log.isInfoEnabled()) {
498             _log.info(
499                 "Hook for " + servletContextName + " is available for use");
500         }
501     }
502 
503     protected void doInvokeUndeploy(HotDeployEvent event) throws Exception {
504         ServletContext servletContext = event.getServletContext();
505 
506         String servletContextName = servletContext.getServletContextName();
507 
508         if (_log.isDebugEnabled()) {
509             _log.debug("Invoking undeploy for " + servletContextName);
510         }
511 
512         if (!_servletContextNames.remove(servletContextName)) {
513             return;
514         }
515 
516         AuthenticatorsContainer authenticatorsContainer =
517             _authenticatorsContainerMap.remove(servletContextName);
518 
519         if (authenticatorsContainer != null) {
520             authenticatorsContainer.unregisterAuthenticators();
521         }
522 
523         AuthFailuresContainer authFailuresContainer =
524             _authFailuresContainerMap.remove(servletContextName);
525 
526         if (authFailuresContainer != null) {
527             authFailuresContainer.unregisterAuthFailures();
528         }
529 
530         AutoDeployListenersContainer autoDeployListenersContainer =
531             _autoDeployListenersContainerMap.remove(servletContextName);
532 
533         if (autoDeployListenersContainer != null) {
534             autoDeployListenersContainer.unregisterAutoDeployListeners();
535         }
536 
537         AutoLoginsContainer autoLoginsContainer =
538             _autoLoginsContainerMap.remove(servletContextName);
539 
540         if (autoLoginsContainer != null) {
541             autoLoginsContainer.unregisterAutoLogins();
542         }
543 
544         CustomJspBag customJspBag = _customJspBagsMap.remove(
545             servletContextName);
546 
547         if (customJspBag != null) {
548             destroyCustomJspBag(customJspBag);
549         }
550 
551         EventsContainer eventsContainer = _eventsContainerMap.remove(
552             servletContextName);
553 
554         if (eventsContainer != null) {
555             eventsContainer.unregisterEvents();
556         }
557 
558         HotDeployListenersContainer hotDeployListenersContainer =
559             _hotDeployListenersContainerMap.remove(servletContextName);
560 
561         if (hotDeployListenersContainer != null) {
562             hotDeployListenersContainer.unregisterHotDeployListeners();
563         }
564 
565         LanguagesContainer languagesContainer = _languagesContainerMap.remove(
566             servletContextName);
567 
568         if (languagesContainer != null) {
569             languagesContainer.unregisterLanguages();
570         }
571 
572         ModelListenersContainer modelListenersContainer =
573             _modelListenersContainerMap.remove(servletContextName);
574 
575         if (modelListenersContainer != null) {
576             modelListenersContainer.unregisterModelListeners();
577         }
578 
579         Properties portalProperties = _portalPropertiesMap.remove(
580             servletContextName);
581 
582         if (portalProperties != null) {
583             destroyPortalProperties(servletContextName, portalProperties);
584         }
585 
586         ServicesContainer servicesContainer = _servicesContainerMap.remove(
587             servletContextName);
588 
589         if (servicesContainer != null) {
590             servicesContainer.unregisterServices();
591         }
592 
593         unregisterClpMessageListeners(servletContext);
594 
595         if (_log.isInfoEnabled()) {
596             _log.info("Hook for " + servletContextName + " was unregistered");
597         }
598     }
599 
600     protected void getCustomJsps(
601         ServletContext servletContext, String webDir, String resourcePath,
602         List<String> customJsps) {
603 
604         Set<String> resourcePaths = servletContext.getResourcePaths(
605             resourcePath);
606 
607         for (String curResourcePath : resourcePaths) {
608             if (curResourcePath.endsWith(StringPool.SLASH)) {
609                 getCustomJsps(
610                     servletContext, webDir, curResourcePath, customJsps);
611             }
612             else {
613                 String customJsp = webDir + curResourcePath;
614 
615                 customJsp = StringUtil.replace(
616                     customJsp, StringPool.DOUBLE_SLASH, StringPool.SLASH);
617 
618                 customJsps.add(customJsp);
619             }
620         }
621     }
622 
623     protected String getLocaleKey(String languagePropertiesLocation) {
624         int x = languagePropertiesLocation.indexOf(StringPool.UNDERLINE);
625         int y = languagePropertiesLocation.indexOf(".properties");
626 
627         if ((x != -1) && (y != 1)) {
628             String localeKey = languagePropertiesLocation.substring(x + 1, y);
629 
630             Locale locale = LocaleUtil.fromLanguageId(localeKey);
631 
632             locale = LanguageUtil.getLocale(locale.getLanguage());
633 
634             if (locale != null) {
635                 return locale.toString();
636             }
637         }
638 
639         return null;
640     }
641 
642     protected BasePersistence<?> getPersistence(String modelName) {
643         int pos = modelName.lastIndexOf(StringPool.PERIOD);
644 
645         String entityName = modelName.substring(pos + 1);
646 
647         pos = modelName.lastIndexOf(".model.");
648 
649         String packagePath = modelName.substring(0, pos);
650 
651         return (BasePersistence<?>)PortalBeanLocatorUtil.locate(
652             packagePath + ".service.persistence." + entityName + "Persistence");
653     }
654 
655     protected File getPortalJspBackupFile(File portalJspFile) {
656         String fileName = portalJspFile.getName();
657         String filePath = portalJspFile.toString();
658 
659         int fileNameIndex = fileName.lastIndexOf(StringPool.PERIOD);
660 
661         if (fileNameIndex > 0) {
662             int filePathIndex = filePath.lastIndexOf(fileName);
663 
664             fileName =
665                 fileName.substring(0, fileNameIndex) + ".portal" +
666                     fileName.substring(fileNameIndex);
667 
668             filePath = filePath.substring(0, filePathIndex) + fileName;
669         }
670         else {
671             filePath += ".portal";
672         }
673 
674         return new File(filePath);
675     }
676 
677     protected void initAuthenticators(
678             ClassLoader portletClassLoader, Properties portalProperties,
679             String key, AuthenticatorsContainer authenticatorsContainer)
680         throws Exception {
681 
682         String[] authenticatorClassNames = StringUtil.split(
683             portalProperties.getProperty(key));
684 
685         for (String authenticatorClassName : authenticatorClassNames) {
686             Authenticator authenticator = (Authenticator)newInstance(
687                 portletClassLoader, Authenticator.class,
688                 authenticatorClassName);
689 
690             authenticatorsContainer.registerAuthenticator(
691                 key, authenticator);
692         }
693     }
694 
695     protected void initAuthenticators(
696             String servletContextName, ClassLoader portletClassLoader,
697             Properties portalProperties)
698         throws Exception {
699 
700         AuthenticatorsContainer authenticatorsContainer =
701             new AuthenticatorsContainer();
702 
703         _authenticatorsContainerMap.put(
704             servletContextName, authenticatorsContainer);
705 
706         initAuthenticators(
707             portletClassLoader, portalProperties, AUTH_PIPELINE_PRE,
708             authenticatorsContainer);
709         initAuthenticators(
710             portletClassLoader, portalProperties, AUTH_PIPELINE_POST,
711             authenticatorsContainer);
712     }
713 
714     protected void initAuthFailures(
715             ClassLoader portletClassLoader, Properties portalProperties,
716             String key, AuthFailuresContainer authFailuresContainer)
717         throws Exception {
718 
719         String[] authFailureClassNames = StringUtil.split(
720             portalProperties.getProperty(key));
721 
722         for (String authFailureClassName : authFailureClassNames) {
723             AuthFailure authFailure = (AuthFailure)newInstance(
724                 portletClassLoader, AuthFailure.class, authFailureClassName);
725 
726             authFailuresContainer.registerAuthFailure(key, authFailure);
727         }
728     }
729 
730     protected void initAuthFailures(
731             String servletContextName, ClassLoader portletClassLoader,
732             Properties portalProperties)
733         throws Exception {
734 
735         AuthFailuresContainer authFailuresContainer =
736             new AuthFailuresContainer();
737 
738         _authFailuresContainerMap.put(
739             servletContextName, authFailuresContainer);
740 
741         initAuthFailures(
742             portletClassLoader, portalProperties, AUTH_FAILURE,
743             authFailuresContainer);
744         initAuthFailures(
745             portletClassLoader, portalProperties, AUTH_MAX_FAILURES,
746             authFailuresContainer);
747     }
748 
749     protected void initAutoDeployListeners(
750             String servletContextName, ClassLoader portletClassLoader,
751             Properties portalProperties)
752         throws Exception {
753 
754         String[] autoDeployListenerClassNames = StringUtil.split(
755             portalProperties.getProperty(PropsKeys.AUTO_DEPLOY_LISTENERS));
756 
757         if (autoDeployListenerClassNames.length == 0) {
758             return;
759         }
760 
761         AutoDeployListenersContainer autoDeployListenersContainer =
762             new AutoDeployListenersContainer();
763 
764         _autoDeployListenersContainerMap.put(
765             servletContextName, autoDeployListenersContainer);
766 
767         for (String autoDeployListenerClassName :
768                 autoDeployListenerClassNames) {
769 
770             AutoDeployListener autoDeployListener =
771                 (AutoDeployListener)newInstance(
772                     portletClassLoader, AutoDeployListener.class,
773                     autoDeployListenerClassName);
774 
775             autoDeployListenersContainer.registerAutoDeployListener(
776                 autoDeployListener);
777         }
778     }
779 
780     protected void initAutoLogins(
781             String servletContextName, ClassLoader portletClassLoader,
782             Properties portalProperties)
783         throws Exception {
784 
785         AutoLoginsContainer autoLoginsContainer = new AutoLoginsContainer();
786 
787         _autoLoginsContainerMap.put(servletContextName, autoLoginsContainer);
788 
789         String[] autoLoginClassNames = StringUtil.split(
790             portalProperties.getProperty(AUTO_LOGIN_HOOKS));
791 
792         for (String autoLoginClassName : autoLoginClassNames) {
793             AutoLogin autoLogin = (AutoLogin)newInstance(
794                 portletClassLoader, AutoLogin.class, autoLoginClassName);
795 
796             autoLoginsContainer.registerAutoLogin(autoLogin);
797         }
798     }
799 
800     protected void initCustomJspBag(CustomJspBag customJspBag)
801         throws Exception {
802 
803         String customJspDir = customJspBag.getCustomJspDir();
804         List<String> customJsps = customJspBag.getCustomJsps();
805         //String timestamp = customJspBag.getTimestamp();
806 
807         String portalWebDir = PortalUtil.getPortalWebDir();
808 
809         for (String customJsp : customJsps) {
810             int pos = customJsp.indexOf(customJspDir);
811 
812             String portalJsp = customJsp.substring(
813                 pos + customJspDir.length(), customJsp.length());
814 
815             File portalJspFile = new File(portalWebDir + portalJsp);
816             File portalJspBackupFile = getPortalJspBackupFile(portalJspFile);
817 
818             if (portalJspFile.exists() && !portalJspBackupFile.exists()) {
819                 FileUtil.copyFile(portalJspFile, portalJspBackupFile);
820             }
821 
822             FileUtil.copyFile(customJsp, portalWebDir + portalJsp);
823         }
824     }
825 
826     protected Object initEvent(
827             String eventName, String eventClassName,
828             ClassLoader portletClassLoader)
829         throws Exception {
830 
831         if (eventName.equals(APPLICATION_STARTUP_EVENTS)) {
832             SimpleAction simpleAction =
833                 (SimpleAction)portletClassLoader.loadClass(
834                     eventClassName).newInstance();
835 
836             simpleAction = new InvokerSimpleAction(
837                 simpleAction, portletClassLoader);
838 
839             long companyId = CompanyThreadLocal.getCompanyId();
840 
841             long[] companyIds = PortalInstances.getCompanyIds();
842 
843             for (long curCompanyId : companyIds) {
844                 CompanyThreadLocal.setCompanyId(curCompanyId);
845 
846                 simpleAction.run(new String[] {String.valueOf(curCompanyId)});
847             }
848 
849             CompanyThreadLocal.setCompanyId(companyId);
850 
851             return null;
852         }
853 
854         if (ArrayUtil.contains(_PROPS_KEYS_EVENTS, eventName)) {
855             Action action = (Action)portletClassLoader.loadClass(
856                 eventClassName).newInstance();
857 
858             action = new InvokerAction(action, portletClassLoader);
859 
860             EventsProcessorUtil.registerEvent(eventName, action);
861 
862             return action;
863         }
864 
865         if (ArrayUtil.contains(_PROPS_KEYS_SESSION_EVENTS, eventName)) {
866             SessionAction sessionAction =
867                 (SessionAction)portletClassLoader.loadClass(
868                     eventClassName).newInstance();
869 
870             sessionAction = new InvokerSessionAction(
871                 sessionAction, portletClassLoader);
872 
873             EventsProcessorUtil.registerEvent(eventName, sessionAction);
874 
875             return sessionAction;
876         }
877 
878         return null;
879     }
880 
881     protected void initEvents(
882             String servletContextName, ClassLoader portletClassLoader,
883             Properties portalProperties)
884         throws Exception {
885 
886         EventsContainer eventsContainer = new EventsContainer();
887 
888         _eventsContainerMap.put(servletContextName, eventsContainer);
889 
890         Iterator<Object> itr = portalProperties.keySet().iterator();
891 
892         while (itr.hasNext()) {
893             String key = (String)itr.next();
894 
895             if (!key.equals(APPLICATION_STARTUP_EVENTS) &&
896                 !ArrayUtil.contains(_PROPS_KEYS_EVENTS, key) &&
897                 !ArrayUtil.contains(_PROPS_KEYS_SESSION_EVENTS, key)) {
898 
899                 continue;
900             }
901 
902             String eventName = key;
903             String[] eventClassNames = StringUtil.split(
904                 portalProperties.getProperty(key));
905 
906             for (String eventClassName : eventClassNames) {
907                 Object obj = initEvent(
908                     eventName, eventClassName, portletClassLoader);
909 
910                 if (obj == null) {
911                     continue;
912                 }
913 
914                 eventsContainer.registerEvent(eventName, obj);
915             }
916         }
917     }
918 
919     protected void initHotDeployListeners(
920             String servletContextName, ClassLoader portletClassLoader,
921             Properties portalProperties)
922         throws Exception {
923 
924         String[] hotDeployListenerClassNames = StringUtil.split(
925             portalProperties.getProperty(PropsKeys.HOT_DEPLOY_LISTENERS));
926 
927         if (hotDeployListenerClassNames.length == 0) {
928             return;
929         }
930 
931         HotDeployListenersContainer hotDeployListenersContainer =
932             new HotDeployListenersContainer();
933 
934         _hotDeployListenersContainerMap.put(
935             servletContextName, hotDeployListenersContainer);
936 
937         for (String hotDeployListenerClassName : hotDeployListenerClassNames) {
938             HotDeployListener hotDeployListener =
939                 (HotDeployListener)newInstance(
940                     portletClassLoader, HotDeployListener.class,
941                     hotDeployListenerClassName);
942 
943             hotDeployListenersContainer.registerHotDeployListener(
944                 hotDeployListener);
945         }
946     }
947 
948     @SuppressWarnings("unchecked")
949     protected ModelListener<BaseModel<?>> initModelListener(
950             String modelName, String modelListenerClassName,
951             ClassLoader portletClassLoader)
952         throws Exception {
953 
954         ModelListener<BaseModel<?>> modelListener =
955             (ModelListener<BaseModel<?>>)newInstance(
956                 portletClassLoader, ModelListener.class,
957                 modelListenerClassName);
958 
959         BasePersistence persistence = getPersistence(modelName);
960 
961         persistence.registerListener(modelListener);
962 
963         return modelListener;
964     }
965 
966     protected void initModelListeners(
967             String servletContextName, ClassLoader portletClassLoader,
968             Properties portalProperties)
969         throws Exception {
970 
971         ModelListenersContainer modelListenersContainer =
972             new ModelListenersContainer();
973 
974         _modelListenersContainerMap.put(
975             servletContextName, modelListenersContainer);
976 
977         Iterator<Object> itr = portalProperties.keySet().iterator();
978 
979         while (itr.hasNext()) {
980             String key = (String)itr.next();
981 
982             if (!key.startsWith(VALUE_OBJECT_LISTENER)) {
983                 continue;
984             }
985 
986             String modelName = key.substring(VALUE_OBJECT_LISTENER.length());
987 
988             String[] modelListenerClassNames = StringUtil.split(
989                 portalProperties.getProperty(key));
990 
991             for (String modelListenerClassName : modelListenerClassNames) {
992                 ModelListener<BaseModel<?>> modelListener = initModelListener(
993                     modelName, modelListenerClassName, portletClassLoader);
994 
995                 if (modelListener != null) {
996                     modelListenersContainer.registerModelListener(
997                         modelName, modelListener);
998                 }
999             }
1000        }
1001    }
1002
1003    protected void initPortalProperties(
1004            String servletContextName, ClassLoader portletClassLoader,
1005            Properties portalProperties)
1006        throws Exception {
1007
1008        PropsUtil.addProperties(portalProperties);
1009
1010        if (_log.isDebugEnabled() && portalProperties.containsKey(LOCALES)) {
1011            _log.debug(
1012                "Portlet locales " + portalProperties.getProperty(LOCALES));
1013            _log.debug("Merged locales " + PropsUtil.get(LOCALES));
1014            _log.debug(
1015                "Merged locales array length " +
1016                    PropsUtil.getArray(LOCALES).length);
1017        }
1018
1019        resetPortalProperties(servletContextName, portalProperties, true);
1020
1021        if (portalProperties.containsKey(
1022                PropsKeys.CONTROL_PANEL_DEFAULT_ENTRY_CLASS)) {
1023
1024            String controlPanelEntryClassName = portalProperties.getProperty(
1025                PropsKeys.CONTROL_PANEL_DEFAULT_ENTRY_CLASS);
1026
1027            ControlPanelEntry controlPanelEntry =
1028                (ControlPanelEntry)newInstance(
1029                    portletClassLoader, ControlPanelEntry.class,
1030                    controlPanelEntryClassName);
1031
1032            DefaultControlPanelEntryFactory.setInstance(controlPanelEntry);
1033        }
1034
1035        if (portalProperties.containsKey(PropsKeys.DL_HOOK_IMPL)) {
1036            String dlHookClassName = portalProperties.getProperty(
1037                PropsKeys.DL_HOOK_IMPL);
1038
1039            com.liferay.documentlibrary.util.Hook dlHook =
1040                (com.liferay.documentlibrary.util.Hook)newInstance(
1041                    portletClassLoader,
1042                    com.liferay.documentlibrary.util.Hook.class,
1043                    dlHookClassName);
1044
1045            com.liferay.documentlibrary.util.HookFactory.setInstance(dlHook);
1046        }
1047
1048        if (portalProperties.containsKey(PropsKeys.IMAGE_HOOK_IMPL)) {
1049            String imageHookClassName = portalProperties.getProperty(
1050                PropsKeys.IMAGE_HOOK_IMPL);
1051
1052            com.liferay.portal.image.Hook imageHook =
1053                (com.liferay.portal.image.Hook)newInstance(
1054                    portletClassLoader, com.liferay.portal.image.Hook.class,
1055                    imageHookClassName);
1056
1057            com.liferay.portal.image.HookFactory.setInstance(imageHook);
1058        }
1059
1060        if (portalProperties.containsKey(
1061                PropsKeys.LDAP_ATTRS_TRANSFORMER_IMPL)) {
1062
1063            String attributesTransformerClassName =
1064                portalProperties.getProperty(
1065                    PropsKeys.LDAP_ATTRS_TRANSFORMER_IMPL);
1066
1067            AttributesTransformer attributesTransformer =
1068                (AttributesTransformer)newInstance(
1069                    portletClassLoader, AttributesTransformer.class,
1070                    attributesTransformerClassName);
1071
1072            AttributesTransformerFactory.setInstance(attributesTransformer);
1073        }
1074
1075        if (portalProperties.containsKey(PropsKeys.MAIL_HOOK_IMPL)) {
1076            String mailHookClassName = portalProperties.getProperty(
1077                PropsKeys.MAIL_HOOK_IMPL);
1078
1079            com.liferay.mail.util.Hook mailHook =
1080                (com.liferay.mail.util.Hook)newInstance(
1081                    portletClassLoader, com.liferay.mail.util.Hook.class,
1082                    mailHookClassName);
1083
1084            com.liferay.mail.util.HookFactory.setInstance(mailHook);
1085        }
1086
1087        if (portalProperties.containsKey(
1088                PropsKeys.USERS_EMAIL_ADDRESS_GENERATOR)) {
1089
1090            String emailAddressGeneratorClassName =
1091                portalProperties.getProperty(
1092                    PropsKeys.USERS_EMAIL_ADDRESS_GENERATOR);
1093
1094            EmailAddressGenerator emailAddressGenerator =
1095                (EmailAddressGenerator)newInstance(
1096                    portletClassLoader, EmailAddressGenerator.class,
1097                    emailAddressGeneratorClassName);
1098
1099            EmailAddressGeneratorFactory.setInstance(emailAddressGenerator);
1100        }
1101
1102        if (portalProperties.containsKey(PropsKeys.USERS_FULL_NAME_VALIDATOR)) {
1103            String fullNameValidatorClassName = portalProperties.getProperty(
1104                PropsKeys.USERS_FULL_NAME_VALIDATOR);
1105
1106            FullNameValidator fullNameValidator =
1107                (FullNameValidator)newInstance(
1108                    portletClassLoader, FullNameValidator.class,
1109                    fullNameValidatorClassName);
1110
1111            FullNameValidatorFactory.setInstance(fullNameValidator);
1112        }
1113
1114        if (portalProperties.containsKey(
1115                PropsKeys.USERS_SCREEN_NAME_GENERATOR)) {
1116
1117            String screenNameGeneratorClassName = portalProperties.getProperty(
1118                PropsKeys.USERS_SCREEN_NAME_GENERATOR);
1119
1120            ScreenNameGenerator screenNameGenerator =
1121                (ScreenNameGenerator)newInstance(
1122                    portletClassLoader, ScreenNameGenerator.class,
1123                    screenNameGeneratorClassName);
1124
1125            ScreenNameGeneratorFactory.setInstance(screenNameGenerator);
1126        }
1127
1128        if (portalProperties.containsKey(
1129                PropsKeys.USERS_SCREEN_NAME_VALIDATOR)) {
1130
1131            String screenNameValidatorClassName = portalProperties.getProperty(
1132                PropsKeys.USERS_SCREEN_NAME_VALIDATOR);
1133
1134            ScreenNameValidator screenNameValidator =
1135                (ScreenNameValidator)newInstance(
1136                    portletClassLoader, ScreenNameValidator.class,
1137                    screenNameValidatorClassName);
1138
1139            ScreenNameValidatorFactory.setInstance(screenNameValidator);
1140        }
1141
1142        if (portalProperties.containsKey(PropsKeys.RELEASE_INFO_BUILD_NUMBER) ||
1143            portalProperties.containsKey(PropsKeys.UPGRADE_PROCESSES)) {
1144
1145            updateRelease(
1146                servletContextName, portletClassLoader, portalProperties);
1147        }
1148    }
1149
1150    protected void resetPortalProperties(
1151            String servletContextName, Properties portalProperties,
1152            boolean initPhase)
1153        throws Exception {
1154
1155        for (String key : _PROPS_VALUES_BOOLEAN) {
1156            String fieldName = StringUtil.replace(
1157                key.toUpperCase(), StringPool.PERIOD,  StringPool.UNDERLINE);
1158
1159            if (!containsKey(portalProperties, key)) {
1160                continue;
1161            }
1162
1163            try {
1164                Field field = PropsValues.class.getField(fieldName);
1165
1166                Boolean value = Boolean.valueOf(GetterUtil.getBoolean(
1167                    PropsUtil.get(key)));
1168
1169                field.setBoolean(null, value);
1170            }
1171            catch (Exception e) {
1172                _log.error(
1173                    "Error setting field " + fieldName + ": " + e.getMessage());
1174            }
1175        }
1176
1177        for (String key : _PROPS_VALUES_INTEGER) {
1178            String fieldName = StringUtil.replace(
1179                key.toUpperCase(), StringPool.PERIOD,  StringPool.UNDERLINE);
1180
1181            if (!containsKey(portalProperties, key)) {
1182                continue;
1183            }
1184
1185            try {
1186                Field field = PropsValues.class.getField(fieldName);
1187
1188                Integer value = Integer.valueOf(GetterUtil.getInteger(
1189                    PropsUtil.get(key)));
1190
1191                field.setInt(null, value);
1192            }
1193            catch (Exception e) {
1194                _log.error(
1195                    "Error setting field " + fieldName + ": " + e.getMessage());
1196            }
1197        }
1198
1199        for (String key : _PROPS_VALUES_LONG) {
1200            String fieldName = StringUtil.replace(
1201                key.toUpperCase(), StringPool.PERIOD,  StringPool.UNDERLINE);
1202
1203            if (!containsKey(portalProperties, key)) {
1204                continue;
1205            }
1206
1207            try {
1208                Field field = PropsValues.class.getField(fieldName);
1209
1210                Long value = Long.valueOf(GetterUtil.getLong(
1211                    PropsUtil.get(key)));
1212
1213                field.setLong(null, value);
1214            }
1215            catch (Exception e) {
1216                _log.error(
1217                    "Error setting field " + fieldName + ": " + e.getMessage());
1218            }
1219        }
1220
1221        for (String key : _PROPS_VALUES_STRING) {
1222            String fieldName = StringUtil.replace(
1223                key.toUpperCase(), StringPool.PERIOD,  StringPool.UNDERLINE);
1224
1225            if (!containsKey(portalProperties, key)) {
1226                continue;
1227            }
1228
1229            try {
1230                Field field = PropsValues.class.getField(fieldName);
1231
1232                String value = GetterUtil.getString(PropsUtil.get(key));
1233
1234                field.set(null, value);
1235            }
1236            catch (Exception e) {
1237                _log.error(
1238                    "Error setting field " + fieldName + ": " + e.getMessage());
1239            }
1240        }
1241
1242        for (String key : _PROPS_VALUES_STRING_ARRAY) {
1243            String fieldName = StringUtil.replace(
1244                key.toUpperCase(), StringPool.PERIOD,  StringPool.UNDERLINE);
1245
1246            if (!containsKey(portalProperties, key)) {
1247                continue;
1248            }
1249
1250            try {
1251                Field field = PropsValues.class.getField(fieldName);
1252
1253                StringArraysContainer stringArraysContainer =
1254                    _stringArraysContainerMap.get(key);
1255
1256                String[] value = null;
1257
1258                if (initPhase) {
1259                    value = PropsUtil.getArray(key);
1260                }
1261
1262                stringArraysContainer.setPluginStringArray(
1263                    servletContextName, value);
1264
1265                value = stringArraysContainer.getMergedStringArray();
1266
1267                field.set(null, value);
1268            }
1269            catch (Exception e) {
1270                _log.error(
1271                    "Error setting field " + fieldName + ": " + e.getMessage());
1272            }
1273        }
1274
1275        if (containsKey(portalProperties, LOCALES)) {
1276            PropsValues.LOCALES = PropsUtil.getArray(LOCALES);
1277
1278            LanguageUtil.init();
1279        }
1280
1281        CacheUtil.clearCache();
1282    }
1283
1284    protected void updateRelease(
1285            String servletContextName, ClassLoader portletClassLoader,
1286            Properties portalProperties)
1287        throws Exception {
1288
1289        int buildNumber = GetterUtil.getInteger(
1290            portalProperties.getProperty(PropsKeys.RELEASE_INFO_BUILD_NUMBER));
1291
1292        if (buildNumber <= 0) {
1293            _log.error(
1294                "Skipping upgrade processes for " + servletContextName +
1295                    " because \"release.info.build.number\" is not specified");
1296
1297            return;
1298        }
1299
1300        Release release = null;
1301
1302        try {
1303            release = ReleaseLocalServiceUtil.getRelease(
1304                servletContextName, buildNumber);
1305        }
1306        catch (PortalException pe) {
1307            int previousBuildNumber = GetterUtil.getInteger(
1308                portalProperties.getProperty(
1309                    PropsKeys.RELEASE_INFO_PREVIOUS_BUILD_NUMBER),
1310                buildNumber);
1311
1312            release = ReleaseLocalServiceUtil.addRelease(
1313                servletContextName, previousBuildNumber);
1314        }
1315
1316        if (buildNumber == release.getBuildNumber()) {
1317            if (_log.isDebugEnabled()) {
1318                _log.debug(
1319                    "Skipping upgrade processes for " + servletContextName +
1320                        " because it is already up to date");
1321            }
1322        }
1323        else if (buildNumber < release.getBuildNumber()) {
1324            throw new UpgradeException(
1325                "Skipping upgrade processes for " + servletContextName +
1326                    " because you are trying to upgrade with an older version");
1327        }
1328        else {
1329            String[] upgradeProcessClassNames = StringUtil.split(
1330                portalProperties.getProperty(PropsKeys.UPGRADE_PROCESSES));
1331
1332            UpgradeProcessUtil.upgradeProcess(
1333                release.getBuildNumber(), upgradeProcessClassNames,
1334                portletClassLoader);
1335        }
1336
1337        ReleaseLocalServiceUtil.updateRelease(
1338            release.getReleaseId(), buildNumber, null, true);
1339    }
1340
1341    private static final String[] _PROPS_KEYS_EVENTS = new String[] {
1342        LOGIN_EVENTS_POST,
1343        LOGIN_EVENTS_PRE,
1344        LOGOUT_EVENTS_POST,
1345        LOGOUT_EVENTS_PRE,
1346        SERVLET_SERVICE_EVENTS_POST,
1347        SERVLET_SERVICE_EVENTS_PRE
1348    };
1349
1350    private static final String[] _PROPS_KEYS_SESSION_EVENTS = new String[] {
1351        SERVLET_SESSION_CREATE_EVENTS,
1352        SERVLET_SESSION_DESTROY_EVENTS
1353    };
1354
1355    private static final String[] _PROPS_VALUES_BOOLEAN = new String[] {
1356        "auth.forward.by.last.path",
1357        "captcha.check.portal.create_account",
1358        "field.enable.com.liferay.portal.model.Contact.birthday",
1359        "field.enable.com.liferay.portal.model.Contact.male",
1360        "field.enable.com.liferay.portal.model.Organization.status",
1361        "javascript.fast.load",
1362        "layout.template.cache.enabled",
1363        "layout.user.private.layouts.auto.create",
1364        "layout.user.private.layouts.enabled",
1365        "layout.user.private.layouts.modifiable",
1366        "layout.user.public.layouts.auto.create",
1367        "layout.user.public.layouts.enabled",
1368        "layout.user.public.layouts.modifiable",
1369        "login.create.account.allow.custom.password",
1370        "my.places.show.community.private.sites.with.no.layouts",
1371        "my.places.show.community.public.sites.with.no.layouts",
1372        "my.places.show.organization.private.sites.with.no.layouts",
1373        "my.places.show.organization.public.sites.with.no.layouts",
1374        "my.places.show.user.private.sites.with.no.layouts",
1375        "my.places.show.user.public.sites.with.no.layouts",
1376        "terms.of.use.required",
1377        "theme.css.fast.load",
1378        "theme.images.fast.load",
1379        "users.email.address.required",
1380        "users.screen.name.always.autogenerate"
1381    };
1382
1383    private static final String[] _PROPS_VALUES_INTEGER = new String[] {
1384    };
1385
1386    private static final String[] _PROPS_VALUES_LONG = new String[] {
1387    };
1388
1389    private static final String[] _PROPS_VALUES_STRING = new String[] {
1390        "default.landing.page.path",
1391        "passwords.passwordpolicytoolkit.generator",
1392        "passwords.passwordpolicytoolkit.static"
1393    };
1394
1395    private static final String[] _PROPS_VALUES_STRING_ARRAY = new String[] {
1396        "layout.static.portlets.all",
1397        "session.phishing.protected.attributes"
1398    };
1399
1400    private static Log _log = LogFactoryUtil.getLog(
1401        HookHotDeployListener.class);
1402
1403    private Map<String, AuthenticatorsContainer> _authenticatorsContainerMap =
1404        new HashMap<String, AuthenticatorsContainer>();
1405    private Map<String, AuthFailuresContainer> _authFailuresContainerMap =
1406        new HashMap<String, AuthFailuresContainer>();
1407    private Map<String, AutoDeployListenersContainer>
1408        _autoDeployListenersContainerMap =
1409            new HashMap<String, AutoDeployListenersContainer>();
1410    private Map<String, AutoLoginsContainer> _autoLoginsContainerMap =
1411        new HashMap<String, AutoLoginsContainer>();
1412    private Map<String, CustomJspBag> _customJspBagsMap =
1413        new HashMap<String, CustomJspBag>();
1414    private Map<String, EventsContainer> _eventsContainerMap =
1415        new HashMap<String, EventsContainer>();
1416    private Map<String, HotDeployListenersContainer>
1417        _hotDeployListenersContainerMap =
1418            new HashMap<String, HotDeployListenersContainer>();
1419    private Map<String, LanguagesContainer> _languagesContainerMap =
1420        new HashMap<String, LanguagesContainer>();
1421    private Map<String, ModelListenersContainer> _modelListenersContainerMap =
1422        new HashMap<String, ModelListenersContainer>();
1423    private Map<String, Properties> _portalPropertiesMap =
1424        new HashMap<String, Properties>();
1425    private Map<String, ServicesContainer> _servicesContainerMap =
1426        new HashMap<String, ServicesContainer>();
1427    private Set<String> _servletContextNames = new HashSet<String>();
1428    private Map<String, StringArraysContainer> _stringArraysContainerMap =
1429        new HashMap<String, StringArraysContainer>();
1430
1431    private class AuthenticatorsContainer {
1432
1433        public void registerAuthenticator(
1434            String key, Authenticator authenticator) {
1435
1436            List<Authenticator> authenticators = _authenticators.get(key);
1437
1438            if (authenticators == null) {
1439                authenticators = new ArrayList<Authenticator>();
1440
1441                _authenticators.put(key, authenticators);
1442            }
1443
1444            AuthPipeline.registerAuthenticator(key, authenticator);
1445
1446            authenticators.add(authenticator);
1447        }
1448
1449        public void unregisterAuthenticators() {
1450            for (Map.Entry<String, List<Authenticator>> entry :
1451                    _authenticators.entrySet()) {
1452
1453                String key = entry.getKey();
1454                List<Authenticator> authenticators = entry.getValue();
1455
1456                for (Authenticator authenticator : authenticators) {
1457                    AuthPipeline.unregisterAuthenticator(key, authenticator);
1458                }
1459            }
1460        }
1461
1462        Map<String, List<Authenticator>> _authenticators =
1463            new HashMap<String, List<Authenticator>>();
1464
1465    }
1466
1467    private class AuthFailuresContainer {
1468
1469        public void registerAuthFailure(String key, AuthFailure authFailure) {
1470            List<AuthFailure> authFailures = _authFailures.get(key);
1471
1472            if (authFailures == null) {
1473                authFailures = new ArrayList<AuthFailure>();
1474
1475                _authFailures.put(key, authFailures);
1476            }
1477
1478            AuthPipeline.registerAuthFailure(key, authFailure);
1479
1480            authFailures.add(authFailure);
1481        }
1482
1483        public void unregisterAuthFailures() {
1484            for (Map.Entry<String, List<AuthFailure>> entry :
1485                    _authFailures.entrySet()) {
1486
1487                String key = entry.getKey();
1488                List<AuthFailure> authFailures = entry.getValue();
1489
1490                for (AuthFailure authFailure : authFailures) {
1491                    AuthPipeline.unregisterAuthFailure(key, authFailure);
1492                }
1493            }
1494        }
1495
1496        Map<String, List<AuthFailure>> _authFailures =
1497            new HashMap<String, List<AuthFailure>>();
1498
1499    }
1500
1501    private class AutoDeployListenersContainer {
1502
1503        public void registerAutoDeployListener(
1504            AutoDeployListener autoDeployListener) {
1505
1506            AutoDeployDir autoDeployDir = AutoDeployUtil.getDir(
1507                AutoDeployDir.DEFAULT_NAME);
1508
1509            if (autoDeployDir == null) {
1510                return;
1511            }
1512
1513            autoDeployDir.registerListener(autoDeployListener);
1514
1515            _autoDeployListeners.add(autoDeployListener);
1516        }
1517
1518        public void unregisterAutoDeployListeners() {
1519            AutoDeployDir autoDeployDir = AutoDeployUtil.getDir(
1520                AutoDeployDir.DEFAULT_NAME);
1521
1522            if (autoDeployDir == null) {
1523                return;
1524            }
1525
1526            for (AutoDeployListener autoDeployListener : _autoDeployListeners) {
1527                autoDeployDir.unregisterListener(autoDeployListener);
1528            }
1529        }
1530
1531        private List<AutoDeployListener> _autoDeployListeners =
1532            new ArrayList<AutoDeployListener>();
1533
1534    }
1535
1536    private class AutoLoginsContainer {
1537
1538        public void registerAutoLogin(AutoLogin autoLogin) {
1539            AutoLoginFilter.registerAutoLogin(autoLogin);
1540
1541            _autoLogins.add(autoLogin);
1542        }
1543
1544        public void unregisterAutoLogins() {
1545            for (AutoLogin autoLogin : _autoLogins) {
1546                AutoLoginFilter.unregisterAutoLogin(autoLogin);
1547            }
1548        }
1549
1550        List<AutoLogin> _autoLogins = new ArrayList<AutoLogin>();
1551
1552    }
1553
1554    private class CustomJspBag {
1555
1556        public CustomJspBag(String customJspDir, List<String> customJsps) {
1557            _customJspDir = customJspDir;
1558            _customJsps = customJsps;
1559        }
1560
1561        public String getCustomJspDir() {
1562            return _customJspDir;
1563        }
1564
1565        public List<String> getCustomJsps() {
1566            return _customJsps;
1567        }
1568
1569        private String _customJspDir;
1570        private List<String> _customJsps;
1571
1572    }
1573
1574    private class EventsContainer {
1575
1576        public void registerEvent(String eventName, Object event) {
1577            List<Object> events = _eventsMap.get(eventName);
1578
1579            if (events == null) {
1580                events = new ArrayList<Object>();
1581
1582                _eventsMap.put(eventName, events);
1583            }
1584
1585            events.add(event);
1586        }
1587
1588        public void unregisterEvents() {
1589            for (Map.Entry<String, List<Object>> entry :
1590                    _eventsMap.entrySet()) {
1591
1592                String eventName = entry.getKey();
1593                List<Object> events = entry.getValue();
1594
1595                for (Object event : events) {
1596                    EventsProcessorUtil.unregisterEvent(eventName, event);
1597                }
1598            }
1599        }
1600
1601        private Map<String, List<Object>> _eventsMap =
1602            new HashMap<String, List<Object>>();
1603
1604    }
1605
1606    private class HotDeployListenersContainer {
1607
1608        public void registerHotDeployListener(
1609            HotDeployListener hotDeployListener) {
1610
1611            HotDeployUtil.registerListener(hotDeployListener);
1612
1613            _hotDeployListeners.add(hotDeployListener);
1614        }
1615
1616        public void unregisterHotDeployListeners() {
1617            for (HotDeployListener hotDeployListener : _hotDeployListeners) {
1618                HotDeployUtil.unregisterListener(hotDeployListener);
1619            }
1620        }
1621
1622        private List<HotDeployListener> _hotDeployListeners =
1623            new ArrayList<HotDeployListener>();
1624
1625    }
1626
1627    private class LanguagesContainer {
1628
1629        public void addLanguage(String localeKey, Properties properties) {
1630            _multiMessageResources.putLocale(localeKey);
1631
1632            Properties oldProperties = _multiMessageResources.putMessages(
1633                properties, localeKey);
1634
1635            _languagesMap.put(localeKey, oldProperties);
1636
1637            LanguageResources.clearCache();
1638        }
1639
1640        public void unregisterLanguages() {
1641            for (String key : _languagesMap.keySet()) {
1642                Properties properties = _languagesMap.get(key);
1643
1644                _multiMessageResources.putMessages(properties, key);
1645            }
1646
1647            LanguageResources.clearCache();
1648        }
1649
1650        private Map<String, Properties> _languagesMap =
1651            new HashMap<String, Properties>();
1652        private MultiMessageResources _multiMessageResources =
1653            MultiMessageResourcesFactory.getInstance();
1654
1655    }
1656
1657    private class ModelListenersContainer {
1658
1659        public void registerModelListener(
1660            String modelName, ModelListener<BaseModel<?>> modelListener) {
1661
1662            List<ModelListener<BaseModel<?>>> modelListeners =
1663                _modelListenersMap.get(modelName);
1664
1665            if (modelListeners == null) {
1666                modelListeners = new ArrayList<ModelListener<BaseModel<?>>>();
1667
1668                _modelListenersMap.put(modelName, modelListeners);
1669            }
1670
1671            modelListeners.add(modelListener);
1672        }
1673
1674        @SuppressWarnings("unchecked")
1675        public void unregisterModelListeners() {
1676            for (Map.Entry<String, List<ModelListener<BaseModel<?>>>> entry :
1677                    _modelListenersMap.entrySet()) {
1678
1679                String modelName = entry.getKey();
1680                List<ModelListener<BaseModel<?>>> modelListeners =
1681                    entry.getValue();
1682
1683                BasePersistence persistence = getPersistence(modelName);
1684
1685                for (ModelListener<BaseModel<?>> modelListener :
1686                        modelListeners) {
1687
1688                    persistence.unregisterListener(modelListener);
1689                }
1690            }
1691        }
1692
1693        private Map<String, List<ModelListener<BaseModel<?>>>>
1694            _modelListenersMap =
1695                new HashMap<String, List<ModelListener<BaseModel<?>>>>();
1696
1697    }
1698
1699    private class ServicesContainer {
1700
1701        public void addService(String serviceType, Object serviceImplInstance) {
1702            ServiceHookAdvice.setService(serviceType, serviceImplInstance);
1703
1704            _serviceTypes.add(serviceType);
1705        }
1706
1707        public void unregisterServices() {
1708            for (String serviceType : _serviceTypes) {
1709                ServiceHookAdvice.setService(serviceType, null);
1710            }
1711        }
1712
1713        private List<String> _serviceTypes = new ArrayList<String>();
1714
1715    }
1716
1717    private class StringArraysContainer {
1718
1719        private StringArraysContainer(String key) {
1720            _portalStringArray = PropsUtil.getArray(key);
1721        }
1722
1723        public String[] getMergedStringArray() {
1724            List<String> mergedStringList = new UniqueList<String>();
1725
1726            mergedStringList.addAll(ListUtil.fromArray(_portalStringArray));
1727
1728            for (Map.Entry<String, String[]> entry :
1729                    _pluginStringArrayMap.entrySet()) {
1730
1731                String[] pluginStringArray = entry.getValue();
1732
1733                mergedStringList.addAll(ListUtil.fromArray(pluginStringArray));
1734            }
1735
1736            return mergedStringList.toArray(
1737                new String[mergedStringList.size()]);
1738        }
1739
1740        public void setPluginStringArray(
1741            String servletContextName, String[] pluginStringArray) {
1742
1743            if (pluginStringArray != null) {
1744                _pluginStringArrayMap.put(
1745                    servletContextName, pluginStringArray);
1746            }
1747            else {
1748                _pluginStringArrayMap.remove(servletContextName);
1749            }
1750        }
1751
1752        private String[] _portalStringArray;
1753        private Map<String, String[]> _pluginStringArrayMap =
1754            new HashMap<String, String[]>();
1755
1756    }
1757
1758}