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