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