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