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