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