1   /**
2    * Copyright (c) 2000-2007 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.events;
24  
25  import com.liferay.portal.LayoutPermissionException;
26  import com.liferay.portal.NoSuchGroupException;
27  import com.liferay.portal.NoSuchLayoutException;
28  import com.liferay.portal.PortalException;
29  import com.liferay.portal.SystemException;
30  import com.liferay.portal.kernel.language.LanguageUtil;
31  import com.liferay.portal.kernel.portlet.LiferayWindowState;
32  import com.liferay.portal.kernel.security.permission.ActionKeys;
33  import com.liferay.portal.kernel.security.permission.PermissionChecker;
34  import com.liferay.portal.kernel.servlet.BrowserSniffer;
35  import com.liferay.portal.kernel.servlet.ImageServletTokenUtil;
36  import com.liferay.portal.kernel.util.GetterUtil;
37  import com.liferay.portal.kernel.util.LocaleUtil;
38  import com.liferay.portal.kernel.util.NullSafeProperties;
39  import com.liferay.portal.kernel.util.ParamUtil;
40  import com.liferay.portal.kernel.util.PropertiesUtil;
41  import com.liferay.portal.kernel.util.StringPool;
42  import com.liferay.portal.kernel.util.StringUtil;
43  import com.liferay.portal.kernel.util.Validator;
44  import com.liferay.portal.model.ColorScheme;
45  import com.liferay.portal.model.Company;
46  import com.liferay.portal.model.Group;
47  import com.liferay.portal.model.Image;
48  import com.liferay.portal.model.Layout;
49  import com.liferay.portal.model.LayoutSet;
50  import com.liferay.portal.model.LayoutTypePortlet;
51  import com.liferay.portal.model.Theme;
52  import com.liferay.portal.model.User;
53  import com.liferay.portal.model.impl.ColorSchemeImpl;
54  import com.liferay.portal.model.impl.GroupImpl;
55  import com.liferay.portal.model.impl.LayoutImpl;
56  import com.liferay.portal.model.impl.LayoutTypePortletImpl;
57  import com.liferay.portal.model.impl.ThemeImpl;
58  import com.liferay.portal.security.permission.PermissionCheckerFactory;
59  import com.liferay.portal.security.permission.PermissionCheckerImpl;
60  import com.liferay.portal.security.permission.PermissionThreadLocal;
61  import com.liferay.portal.service.GroupLocalServiceUtil;
62  import com.liferay.portal.service.LayoutLocalServiceUtil;
63  import com.liferay.portal.service.OrganizationLocalServiceUtil;
64  import com.liferay.portal.service.UserLocalServiceUtil;
65  import com.liferay.portal.service.impl.ImageLocalUtil;
66  import com.liferay.portal.service.impl.ThemeLocalUtil;
67  import com.liferay.portal.service.permission.GroupPermissionUtil;
68  import com.liferay.portal.service.permission.LayoutPermissionUtil;
69  import com.liferay.portal.service.permission.OrganizationPermissionUtil;
70  import com.liferay.portal.service.permission.UserPermissionUtil;
71  import com.liferay.portal.struts.Action;
72  import com.liferay.portal.struts.ActionException;
73  import com.liferay.portal.theme.ThemeDisplay;
74  import com.liferay.portal.theme.ThemeDisplayFactory;
75  import com.liferay.portal.util.CookieKeys;
76  import com.liferay.portal.util.LayoutClone;
77  import com.liferay.portal.util.LayoutCloneFactory;
78  import com.liferay.portal.util.PortalUtil;
79  import com.liferay.portal.util.PortletKeys;
80  import com.liferay.portal.util.PropsUtil;
81  import com.liferay.portal.util.WebKeys;
82  import com.liferay.portlet.PortletURLImpl;
83  import com.liferay.util.CookieUtil;
84  import com.liferay.util.ListUtil;
85  import com.liferay.util.dao.hibernate.QueryUtil;
86  import com.liferay.util.servlet.SessionErrors;
87  
88  import java.util.ArrayList;
89  import java.util.LinkedHashMap;
90  import java.util.List;
91  import java.util.Locale;
92  import java.util.Properties;
93  import java.util.TimeZone;
94  
95  import javax.portlet.PortletMode;
96  import javax.portlet.PortletURL;
97  import javax.portlet.WindowState;
98  
99  import javax.servlet.http.HttpServletRequest;
100 import javax.servlet.http.HttpServletResponse;
101 import javax.servlet.http.HttpSession;
102 
103 import org.apache.commons.lang.time.StopWatch;
104 import org.apache.commons.logging.Log;
105 import org.apache.commons.logging.LogFactory;
106 import org.apache.struts.Globals;
107 
108 /**
109  * <a href="ServicePreAction.java.html"><b><i>View Source</i></b></a>
110  *
111  * @author Brian Wing Shun Chan
112  * @author Felix Ventero
113  *
114  */
115 public class ServicePreAction extends Action {
116 
117     public void run(HttpServletRequest req, HttpServletResponse res)
118         throws ActionException {
119 
120         StopWatch stopWatch = null;
121 
122         if (_log.isDebugEnabled()) {
123             stopWatch = new StopWatch();
124 
125             stopWatch.start();
126         }
127 
128         try {
129             servicePre(req, res);
130         }
131         catch (Exception e) {
132             _log.error(e, e);
133 
134             throw new ActionException(e);
135         }
136 
137         if (_log.isDebugEnabled()) {
138             _log.debug("Running takes " + stopWatch.getTime() + " ms");
139         }
140     }
141 
142     protected void addDefaultLayouts(User user)
143         throws PortalException, SystemException {
144 
145         if (user.hasPrivateLayouts()) {
146             return;
147         }
148 
149         Group userGroup = user.getGroup();
150 
151         String name = PropsUtil.get(PropsUtil.DEFAULT_USER_LAYOUT_NAME);
152 
153         Layout layout = LayoutLocalServiceUtil.addLayout(
154             user.getUserId(), userGroup.getGroupId(), true,
155             LayoutImpl.DEFAULT_PARENT_LAYOUT_ID, name, StringPool.BLANK,
156             StringPool.BLANK, LayoutImpl.TYPE_PORTLET, false, StringPool.BLANK);
157 
158         LayoutTypePortlet layoutTypePortlet =
159             (LayoutTypePortlet)layout.getLayoutType();
160 
161         String layoutTemplateId = PropsUtil.get(
162             PropsUtil.DEFAULT_USER_LAYOUT_TEMPLATE_ID);
163 
164         layoutTypePortlet.setLayoutTemplateId(0, layoutTemplateId, false);
165 
166         for (int i = 0; i < 10; i++) {
167             String columnId = "column-" + i;
168             String portletIds = PropsUtil.get(
169                 PropsUtil.DEFAULT_USER_LAYOUT_COLUMN + i);
170 
171             String[] portletIdsArray = StringUtil.split(portletIds);
172 
173             layoutTypePortlet.addPortletIds(
174                 0, portletIdsArray, columnId, false);
175         }
176 
177         LayoutLocalServiceUtil.updateLayout(
178             layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(),
179             layout.getTypeSettings());
180     }
181 
182     protected void deleteDefaultLayouts(User user)
183         throws PortalException, SystemException {
184 
185         if (user.hasPrivateLayouts()) {
186             Group userGroup = user.getGroup();
187 
188             LayoutLocalServiceUtil.deleteLayouts(userGroup.getGroupId(), true);
189         }
190 
191         if (user.hasPublicLayouts()) {
192             Group userGroup = user.getGroup();
193 
194             LayoutLocalServiceUtil.deleteLayouts(userGroup.getGroupId(), false);
195         }
196     }
197 
198     protected void fixState(HttpServletRequest req, ThemeDisplay themeDisplay)
199         throws PortalException, SystemException {
200 
201         String requestURI = GetterUtil.getString(req.getRequestURI());
202 
203         if (!requestURI.endsWith("/portal/layout")) {
204             return;
205         }
206 
207         Layout layout = themeDisplay.getLayout();
208 
209         if ((layout == null) ||
210             (!layout.getType().equals(LayoutImpl.TYPE_PORTLET))) {
211 
212             return;
213         }
214 
215         LayoutTypePortlet layoutTypePortlet =
216             themeDisplay.getLayoutTypePortlet();
217 
218         // Fix pop up state
219 
220         String stateMaxPrevious = layoutTypePortlet.getStateMaxPrevious();
221 
222         if (stateMaxPrevious != null && !themeDisplay.isStatePopUp()) {
223             layoutTypePortlet.removeStateMaxPrevious();
224 
225             if (stateMaxPrevious.equals(StringPool.BLANK)) {
226                 layoutTypePortlet.setStateMax(StringPool.BLANK);
227             }
228             else {
229                 layoutTypePortlet.setStateMax(stateMaxPrevious);
230             }
231         }
232 
233         // Fix maximized state
234 
235         if (layoutTypePortlet.hasStateMax()) {
236             String portletId =
237                 StringUtil.split(layoutTypePortlet.getStateMax())[0];
238 
239             boolean removeStateMax = false;
240 
241             if (!GetterUtil.getBoolean(PropsUtil.get(PropsUtil.
242                     LAYOUT_REMEMBER_REQUEST_WINDOW_STATE_MAXIMIZED)) &&
243                 Validator.isNotNull(portletId)) {
244 
245                 removeStateMax = true;
246             }
247 
248             // If a user accesses a maximized portlet that is not a part of the
249             // layout, the maximized portlet should be removed the next time the
250             // layout is accessed.
251 
252             if (!layoutTypePortlet.hasPortletId(portletId)) {
253                 removeStateMax = true;
254             }
255 
256             if (removeStateMax) {
257                 String ppState = ParamUtil.getString(req, "p_p_state");
258 
259                 if (Validator.isNull(ppState) ||
260                     ppState.equals(WindowState.NORMAL.toString())) {
261 
262                     layoutTypePortlet.removeStateMaxPortletId(portletId);
263 
264                     String typeSettings = layout.getTypeSettings();
265                 }
266             }
267         }
268     }
269 
270     protected Object[] getDefaultLayout(
271             HttpServletRequest req, User user, boolean signedIn)
272         throws PortalException, SystemException {
273 
274         // Check the virtual host
275 
276         LayoutSet layoutSet = (LayoutSet)req.getAttribute(
277             WebKeys.VIRTUAL_HOST_LAYOUT_SET);
278 
279         if (layoutSet != null) {
280             List layouts = LayoutLocalServiceUtil.getLayouts(
281                 layoutSet.getGroupId(), layoutSet.isPrivateLayout(),
282                 LayoutImpl.DEFAULT_PARENT_LAYOUT_ID);
283 
284             if (layouts.size() > 0) {
285                 Layout layout = (Layout)layouts.get(0);
286 
287                 return new Object[] {layout, layouts};
288             }
289         }
290 
291         Layout layout = null;
292         List layouts = null;
293 
294         if (signedIn) {
295 
296             // Check the user's personal layouts
297 
298             Group userGroup = user.getGroup();
299 
300             layouts = LayoutLocalServiceUtil.getLayouts(
301                 userGroup.getGroupId(), true,
302                 LayoutImpl.DEFAULT_PARENT_LAYOUT_ID);
303 
304             if (layouts.size() == 0) {
305                 layouts = LayoutLocalServiceUtil.getLayouts(
306                     userGroup.getGroupId(), false,
307                     LayoutImpl.DEFAULT_PARENT_LAYOUT_ID);
308             }
309 
310             if (layouts.size() > 0) {
311                 layout = (Layout)layouts.get(0);
312             }
313 
314             // Check the user's communities
315 
316             if (layout == null) {
317                 LinkedHashMap groupParams = new LinkedHashMap();
318 
319                 groupParams.put("usersGroups", new Long(user.getUserId()));
320 
321                 List groups = GroupLocalServiceUtil.search(
322                     user.getCompanyId(), null, null, groupParams,
323                     QueryUtil.ALL_POS, QueryUtil.ALL_POS);
324 
325                 for (int i = 0; i < groups.size(); i++) {
326                     Group group = (Group)groups.get(i);
327 
328                     layouts = LayoutLocalServiceUtil.getLayouts(
329                         group.getGroupId(), true,
330                         LayoutImpl.DEFAULT_PARENT_LAYOUT_ID);
331 
332                     if (layouts.size() == 0) {
333                         layouts = LayoutLocalServiceUtil.getLayouts(
334                             group.getGroupId(), false,
335                             LayoutImpl.DEFAULT_PARENT_LAYOUT_ID);
336                     }
337 
338                     if (layouts.size() > 0) {
339                         layout = (Layout)layouts.get(0);
340 
341                         break;
342                     }
343                 }
344             }
345         }
346         else {
347 
348             // Check the guest community
349 
350             Group guestGroup = GroupLocalServiceUtil.getGroup(
351                 user.getCompanyId(), GroupImpl.GUEST);
352 
353             layouts = LayoutLocalServiceUtil.getLayouts(
354                 guestGroup.getGroupId(), false,
355                 LayoutImpl.DEFAULT_PARENT_LAYOUT_ID);
356 
357             if (layouts.size() > 0) {
358                 layout = (Layout)layouts.get(0);
359             }
360         }
361 
362         return new Object[] {layout, layouts};
363     }
364 
365     protected Object[] getViewableLayouts(
366             HttpServletRequest req, User user,
367             PermissionChecker permissionChecker, Layout layout, List layouts)
368         throws PortalException, SystemException {
369 
370         if ((layouts != null) && (layouts.size() > 0)) {
371             boolean replaceLayout = true;
372 
373             if (LayoutPermissionUtil.contains(
374                     permissionChecker, layout, ActionKeys.VIEW)) {
375 
376                 replaceLayout = false;
377             }
378 
379             List accessibleLayouts = new ArrayList();
380 
381             for (int i = 0; i < layouts.size(); i++) {
382                 Layout curLayout = (Layout)layouts.get(i);
383 
384                 if (!curLayout.isHidden() &&
385                     LayoutPermissionUtil.contains(
386                         permissionChecker, curLayout, ActionKeys.VIEW)) {
387 
388                     if ((accessibleLayouts.size() == 0) && replaceLayout) {
389                         layout = curLayout;
390                     }
391 
392                     accessibleLayouts.add(curLayout);
393                 }
394             }
395 
396             if (accessibleLayouts.size() == 0) {
397                 layouts = null;
398 
399                 SessionErrors.add(
400                     req, LayoutPermissionException.class.getName());
401             }
402             else {
403                 layouts = accessibleLayouts;
404             }
405         }
406 
407         return new Object[] {layout, layouts};
408     }
409 
410     protected boolean isViewableCommunity(
411             User user, long groupId, boolean privateLayout,
412             PermissionChecker permissionChecker)
413         throws PortalException, SystemException {
414 
415         // Public layouts are always viewable
416 
417         if (!privateLayout) {
418             return true;
419         }
420 
421         // User private layouts are only viewable by the user and anyone who can
422         // update the user
423 
424         Group group = GroupLocalServiceUtil.getGroup(groupId);
425 
426         if (group.isUser()) {
427             long groupUserId = group.getClassPK();
428 
429             if (groupUserId == user.getUserId()) {
430                 return true;
431             }
432             else {
433                 User groupUser = UserLocalServiceUtil.getUserById(groupUserId);
434 
435                 if (UserPermissionUtil.contains(
436                         permissionChecker, groupUserId,
437                         groupUser.getOrganization().getOrganizationId(),
438                         groupUser.getLocation().getOrganizationId(),
439                         ActionKeys.UPDATE)) {
440 
441                     return true;
442                 }
443                 else {
444                     return false;
445                 }
446             }
447         }
448 
449         // If the current group is staging, the live group should be checked
450         // for membership instead
451 
452         if (group.isStagingGroup()) {
453             groupId = group.getLiveGroupId();
454         }
455 
456         // Community or organization layhous are only viewable by users who
457         // belong to the community or organization, or by users who can update
458         // the community or organization
459 
460         if (group.isCommunity()) {
461             if (GroupLocalServiceUtil.hasUserGroup(user.getUserId(), groupId)) {
462                 return true;
463             }
464             else if (GroupPermissionUtil.contains(
465                         permissionChecker, groupId, ActionKeys.UPDATE)) {
466 
467                 return true;
468             }
469         }
470         else if (group.isOrganization()) {
471             long organizationId = group.getClassPK();
472 
473             if (OrganizationLocalServiceUtil.hasUserOrganization(
474                     user.getUserId(), organizationId)) {
475 
476                 return true;
477             }
478             else if (OrganizationPermissionUtil.contains(
479                         permissionChecker, organizationId, ActionKeys.UPDATE)) {
480 
481                 return true;
482             }
483         }
484 
485         return false;
486     }
487 
488     protected List mergeAdditionalLayouts(
489             User user, Layout layout, List layouts, HttpServletRequest req)
490         throws PortalException, SystemException {
491 
492         if ((layout == null) || layout.isPrivateLayout()) {
493             return layouts;
494         }
495 
496         long layoutGroupId = layout.getGroupId();
497 
498         Group guestGroup = GroupLocalServiceUtil.getGroup(
499             user.getCompanyId(), GroupImpl.GUEST);
500 
501         if (layoutGroupId != guestGroup.getGroupId()) {
502             Group layoutGroup = GroupLocalServiceUtil.getGroup(layoutGroupId);
503 
504             Properties props = layoutGroup.getTypeSettingsProperties();
505 
506             boolean mergeGuestPublicPages = GetterUtil.getBoolean(
507                 props.getProperty("mergeGuestPublicPages"));
508 
509             if (!mergeGuestPublicPages) {
510                 return layouts;
511             }
512 
513             List guestLayouts = LayoutLocalServiceUtil.getLayouts(
514                 guestGroup.getGroupId(), false,
515                 LayoutImpl.DEFAULT_PARENT_LAYOUT_ID);
516 
517             layouts.addAll(0, guestLayouts);
518         }
519         else {
520             HttpSession ses = req.getSession();
521 
522             Long previousGroupId = (Long)ses.getAttribute(
523                 WebKeys.LIFERAY_SHARED_VISITED_GROUP_ID_PREVIOUS);
524 
525             if ((previousGroupId != null) &&
526                 (previousGroupId.longValue() != layoutGroupId)) {
527 
528                 Group previousGroup = null;
529 
530                 try {
531                     previousGroup = GroupLocalServiceUtil.getGroup(
532                         previousGroupId.longValue());
533                 }
534                 catch (NoSuchGroupException nsge) {
535                     if (_log.isWarnEnabled()) {
536                         _log.warn(nsge);
537                     }
538 
539                     return layouts;
540                 }
541 
542                 Properties props = previousGroup.getTypeSettingsProperties();
543 
544                 boolean mergeGuestPublicPages = GetterUtil.getBoolean(
545                     props.getProperty("mergeGuestPublicPages"));
546 
547                 if (!mergeGuestPublicPages) {
548                     return layouts;
549                 }
550 
551                 List previousLayouts = LayoutLocalServiceUtil.getLayouts(
552                     previousGroupId.longValue(), false,
553                     LayoutImpl.DEFAULT_PARENT_LAYOUT_ID);
554 
555                 layouts.addAll(previousLayouts);
556             }
557         }
558 
559         return layouts;
560     }
561 
562     protected void rememberVisitedGroupIds(
563         long currentGroupId, HttpServletRequest req) {
564 
565         String requestURI = GetterUtil.getString(req.getRequestURI());
566 
567         if (!requestURI.endsWith(_PATH_PORTAL_LAYOUT)) {
568             return;
569         }
570 
571         HttpSession ses = req.getSession();
572 
573         Long recentGroupId = (Long)ses.getAttribute(
574             WebKeys.LIFERAY_SHARED_VISITED_GROUP_ID_RECENT);
575 
576         Long previousGroupId = (Long)ses.getAttribute(
577             WebKeys.LIFERAY_SHARED_VISITED_GROUP_ID_PREVIOUS);
578 
579         if (recentGroupId == null) {
580             recentGroupId = new Long(currentGroupId);
581 
582             ses.setAttribute(
583                 WebKeys.LIFERAY_SHARED_VISITED_GROUP_ID_RECENT,
584                 recentGroupId);
585         }
586         else if (recentGroupId.longValue() != currentGroupId) {
587             previousGroupId = new Long(recentGroupId.longValue());
588 
589             recentGroupId = new Long(currentGroupId);
590 
591             ses.setAttribute(
592                 WebKeys.LIFERAY_SHARED_VISITED_GROUP_ID_RECENT,
593                 recentGroupId);
594 
595             ses.setAttribute(
596                 WebKeys.LIFERAY_SHARED_VISITED_GROUP_ID_PREVIOUS,
597                 previousGroupId);
598         }
599 
600         if (_log.isDebugEnabled()) {
601             _log.debug("Current group id " + currentGroupId);
602             _log.debug("Recent group id " + recentGroupId);
603             _log.debug("Previous group id " + previousGroupId);
604         }
605     }
606 
607     protected void servicePre(HttpServletRequest req, HttpServletResponse res)
608         throws Exception {
609 
610         HttpSession ses = req.getSession();
611 
612         // Company
613 
614         Company company = PortalUtil.getCompany(req);
615 
616         long companyId = company.getCompanyId();
617 
618         // CDN host
619 
620         String cdnHost = ParamUtil.getString(
621             req, "cdn_host", PortalUtil.getCDNHost());
622 
623         // Paths
624 
625         String contextPath = PortalUtil.getPathContext();
626         String friendlyURLPrivateGroupPath =
627             PortalUtil.getPathFriendlyURLPrivateGroup();
628         String friendlyURLPrivateUserPath =
629             PortalUtil.getPathFriendlyURLPrivateUser();
630         String friendlyURLPublicPath = PortalUtil.getPathFriendlyURLPublic();
631         String imagePath = PortalUtil.getPathImage();
632         String mainPath = PortalUtil.getPathMain();
633 
634         // Company logo
635 
636         String companyLogo =
637             imagePath + "/company_logo?img_id=" + company.getLogoId() + "&t=" +
638                 ImageServletTokenUtil.getToken(company.getLogoId());
639 
640         Image companyLogoImage = ImageLocalUtil.getCompanyLogo(
641             company.getLogoId());
642 
643         int companyLogoHeight = companyLogoImage.getHeight();
644         int companyLogoWidth = companyLogoImage.getWidth();
645 
646         String realCompanyLogo = companyLogo;
647         int realCompanyLogoHeight = companyLogoHeight;
648         int realCompanyLogoWidth = companyLogoWidth;
649 
650         // User
651 
652         User user = PortalUtil.getUser(req);
653 
654         boolean signedIn = false;
655 
656         if (user == null) {
657             user = company.getDefaultUser();
658         }
659         else if (!user.isDefaultUser()) {
660             signedIn = true;
661         }
662 
663         User realUser = user;
664 
665         Long realUserId = (Long)ses.getAttribute(WebKeys.USER_ID);
666 
667         if (realUserId != null) {
668             if (user.getUserId() != realUserId.longValue()) {
669                 realUser = UserLocalServiceUtil.getUserById(
670                     realUserId.longValue());
671             }
672         }
673 
674         String doAsUserId = ParamUtil.getString(req, "doAsUserId");
675 
676         // Permission checker
677 
678         PermissionCheckerImpl permissionChecker =
679             PermissionCheckerFactory.create(user, true);
680 
681         PermissionThreadLocal.setPermissionChecker(permissionChecker);
682 
683         // Locale
684 
685         Locale locale = (Locale)ses.getAttribute(Globals.LOCALE_KEY);
686 
687         if (locale == null) {
688             if (signedIn) {
689                 locale = user.getLocale();
690             }
691             else {
692 
693                 // User previously set their preferred language
694 
695                 String languageId = CookieUtil.get(
696                     req.getCookies(), CookieKeys.GUEST_LANGUAGE_ID);
697 
698                 if (Validator.isNotNull(languageId)) {
699                     locale = LocaleUtil.fromLanguageId(languageId);
700                 }
701 
702                 // Get locale from the request
703 
704                 if ((locale == null) &&
705                     GetterUtil.getBoolean(
706                         PropsUtil.get(PropsUtil.LOCALE_DEFAULT_REQUEST))) {
707 
708                     locale = req.getLocale();
709                 }
710 
711                 // Get locale from the default user
712 
713                 if (locale == null) {
714                     locale = user.getLocale();
715                 }
716 
717                 if (Validator.isNull(locale.getCountry())) {
718 
719                     // Locales must contain the country code
720 
721                     locale = LanguageUtil.getLocale(locale.getLanguage());
722                 }
723 
724                 List availableLocales = ListUtil.fromArray(
725                     LanguageUtil.getAvailableLocales());
726 
727                 if (!availableLocales.contains(locale)) {
728                     locale = user.getLocale();
729                 }
730             }
731 
732             ses.setAttribute(Globals.LOCALE_KEY, locale);
733 
734             LanguageUtil.updateCookie(res, locale);
735         }
736 
737         // Cookie support
738 
739         try {
740 
741             // LEP-4069
742 
743             CookieKeys.validateSupportCookie(req);
744         }
745         catch (Exception e) {
746             CookieKeys.addSupportCookie(res);
747         }
748 
749         // Time zone
750 
751         TimeZone timeZone = user.getTimeZone();
752 
753         if (timeZone == null) {
754             timeZone = company.getTimeZone();
755         }
756 
757         // Layouts
758 
759         if (signedIn) {
760             boolean layoutsRequired = user.isLayoutsRequired();
761 
762             if (layoutsRequired) {
763                 addDefaultLayouts(user);
764             }
765             else {
766                 deleteDefaultLayouts(user);
767             }
768         }
769 
770         Layout layout = null;
771         List layouts = null;
772 
773         long plid = ParamUtil.getLong(req, "p_l_id");
774 
775         if (plid > 0) {
776             try {
777                 layout = LayoutLocalServiceUtil.getLayout(plid);
778 
779                 if (!signedIn &&
780                     GetterUtil.getBoolean(PropsUtil.get(
781                         PropsUtil.AUTH_FORWARD_BY_REDIRECT))) {
782 
783                     req.setAttribute(WebKeys.REQUESTED_LAYOUT, layout);
784                 }
785 
786                 boolean isViewableCommunity = isViewableCommunity(
787                     user, layout.getGroupId(), layout.isPrivateLayout(),
788                     permissionChecker);
789 
790                 if (!isViewableCommunity) {
791                     layout = null;
792                 }
793                 else if (isViewableCommunity &&
794                         !LayoutPermissionUtil.contains(
795                             permissionChecker, layout, ActionKeys.VIEW)) {
796 
797                     layout = null;
798                 }
799                 else {
800                     layouts = LayoutLocalServiceUtil.getLayouts(
801                         layout.getGroupId(), layout.isPrivateLayout(),
802                         LayoutImpl.DEFAULT_PARENT_LAYOUT_ID);
803                 }
804             }
805             catch (NoSuchLayoutException nsle) {
806             }
807         }
808 
809         if (layout == null) {
810             Object[] defaultLayout = getDefaultLayout(req, user, signedIn);
811 
812             layout = (Layout)defaultLayout[0];
813             layouts = (List)defaultLayout[1];
814 
815             req.setAttribute(WebKeys.LAYOUT_DEFAULT, Boolean.TRUE);
816         }
817 
818         Object[] viewableLayouts = getViewableLayouts(
819             req, user, permissionChecker, layout, layouts);
820 
821         String layoutSetLogo = null;
822 
823         layout = (Layout)viewableLayouts[0];
824         layouts = (List)viewableLayouts[1];
825 
826         long portletGroupId = PortalUtil.getPortletGroupId(layout);
827 
828         rememberVisitedGroupIds(portletGroupId, req);
829 
830         layouts = mergeAdditionalLayouts(user, layout, layouts, req);
831 
832         if (layout != null) {
833             if (company.isCommunityLogo()) {
834                 LayoutSet layoutSet = layout.getLayoutSet();
835 
836                 if (layoutSet.isLogo()) {
837                     long logoId = layoutSet.getLogoId();
838 
839                     layoutSetLogo =
840                         imagePath + "/layout_set_logo?img_id=" + logoId +
841                             "&t=" + ImageServletTokenUtil.getToken(logoId);
842 
843                     Image layoutSetLogoImage = ImageLocalUtil.getCompanyLogo(
844                         logoId);
845 
846                     companyLogo = layoutSetLogo;
847                     companyLogoHeight = layoutSetLogoImage.getHeight();
848                     companyLogoWidth = layoutSetLogoImage.getWidth();
849                 }
850             }
851 
852             plid = layout.getPlid();
853         }
854 
855         if (layout != null) {
856 
857             // Updates to shared layouts are not reflected until the next time
858             // the user logs in because group layouts are cached in the session
859 
860             layout = (Layout)((LayoutImpl)layout).clone();
861 
862             LayoutClone layoutClone = LayoutCloneFactory.getInstance();
863 
864             if (layoutClone != null) {
865                 String typeSettings = layoutClone.get(req, layout.getPlid());
866 
867                 if (typeSettings != null) {
868                     Properties props = new NullSafeProperties();
869 
870                     PropertiesUtil.load(props, typeSettings);
871 
872                     String stateMax = props.getProperty(
873                         LayoutTypePortletImpl.STATE_MAX);
874                     String stateMaxPrevious = props.getProperty(
875                         LayoutTypePortletImpl.STATE_MAX_PREVIOUS);
876                     String stateMin = props.getProperty(
877                         LayoutTypePortletImpl.STATE_MIN);
878                     String modeAbout = props.getProperty(
879                         LayoutTypePortletImpl.MODE_ABOUT);
880                     String modeConfig = props.getProperty(
881                         LayoutTypePortletImpl.MODE_CONFIG);
882                     String modeEdit = props.getProperty(
883                         LayoutTypePortletImpl.MODE_EDIT);
884                     String modeEditDefaults = props.getProperty(
885                         LayoutTypePortletImpl.MODE_EDIT_DEFAULTS);
886                     String modeEditGuest = props.getProperty(
887                         LayoutTypePortletImpl.MODE_EDIT_GUEST);
888                     String modeHelp = props.getProperty(
889                         LayoutTypePortletImpl.MODE_HELP);
890                     String modePreview = props.getProperty(
891                         LayoutTypePortletImpl.MODE_PREVIEW);
892                     String modePrint = props.getProperty(
893                         LayoutTypePortletImpl.MODE_PRINT);
894 
895                     LayoutTypePortlet layoutTypePortlet =
896                         (LayoutTypePortlet)layout.getLayoutType();
897 
898                     layoutTypePortlet.setStateMax(stateMax);
899                     layoutTypePortlet.setStateMaxPrevious(stateMaxPrevious);
900                     layoutTypePortlet.setStateMin(stateMin);
901                     layoutTypePortlet.setModeAbout(modeAbout);
902                     layoutTypePortlet.setModeConfig(modeConfig);
903                     layoutTypePortlet.setModeEdit(modeEdit);
904                     layoutTypePortlet.setModeEditDefaults(modeEditDefaults);
905                     layoutTypePortlet.setModeEditGuest(modeEditGuest);
906                     layoutTypePortlet.setModeHelp(modeHelp);
907                     layoutTypePortlet.setModePreview(modePreview);
908                     layoutTypePortlet.setModePrint(modePrint);
909                 }
910             }
911         }
912 
913         LayoutTypePortlet layoutTypePortlet = null;
914 
915         if (layout != null) {
916             req.setAttribute(WebKeys.LAYOUT, layout);
917             req.setAttribute(WebKeys.LAYOUTS, layouts);
918 
919             layoutTypePortlet = (LayoutTypePortlet)layout.getLayoutType();
920 
921             if (layout.isPrivateLayout()) {
922                 permissionChecker.setCheckGuest(false);
923             }
924         }
925 
926         // Theme and color scheme
927 
928         Theme theme = null;
929         ColorScheme colorScheme = null;
930 
931         boolean wapTheme = BrowserSniffer.is_wap_xhtml(req);
932 
933         if (layout != null) {
934             if (wapTheme) {
935                 theme = layout.getWapTheme();
936                 colorScheme = layout.getWapColorScheme();
937             }
938             else {
939                 theme = layout.getTheme();
940                 colorScheme = layout.getColorScheme();
941             }
942         }
943         else {
944             String themeId = null;
945             String colorSchemeId = null;
946 
947             if (wapTheme) {
948                 themeId = ThemeImpl.getDefaultWapThemeId();
949                 colorSchemeId = ColorSchemeImpl.getDefaultWapColorSchemeId();
950             }
951             else {
952                 themeId = ThemeImpl.getDefaultRegularThemeId();
953                 colorSchemeId =
954                     ColorSchemeImpl.getDefaultRegularColorSchemeId();
955             }
956 
957             theme = ThemeLocalUtil.getTheme(companyId, themeId, wapTheme);
958             colorScheme = ThemeLocalUtil.getColorScheme(
959                 companyId, theme.getThemeId(), colorSchemeId, wapTheme);
960         }
961 
962         req.setAttribute(WebKeys.THEME, theme);
963         req.setAttribute(WebKeys.COLOR_SCHEME, colorScheme);
964 
965         // Theme display
966 
967         ThemeDisplay themeDisplay = ThemeDisplayFactory.create();
968 
969         // Set the CDN host first because other methods (setLookAndFeel) depend
970         // on it being set
971 
972         themeDisplay.setCDNHost(cdnHost);
973 
974         themeDisplay.setCompany(company);
975         themeDisplay.setCompanyLogo(companyLogo);
976         themeDisplay.setCompanyLogoHeight(companyLogoHeight);
977         themeDisplay.setCompanyLogoWidth(companyLogoWidth);
978         themeDisplay.setRealCompanyLogo(realCompanyLogo);
979         themeDisplay.setRealCompanyLogoHeight(realCompanyLogoHeight);
980         themeDisplay.setRealCompanyLogoWidth(realCompanyLogoWidth);
981         themeDisplay.setUser(user);
982         themeDisplay.setRealUser(realUser);
983         themeDisplay.setDoAsUserId(doAsUserId);
984         themeDisplay.setLayoutSetLogo(layoutSetLogo);
985         themeDisplay.setLayout(layout);
986         themeDisplay.setLayouts(layouts);
987         themeDisplay.setPlid(plid);
988         themeDisplay.setLayoutTypePortlet(layoutTypePortlet);
989         themeDisplay.setPortletGroupId(portletGroupId);
990         themeDisplay.setSignedIn(signedIn);
991         themeDisplay.setPermissionChecker(permissionChecker);
992         themeDisplay.setLocale(locale);
993         themeDisplay.setLanguageId(LocaleUtil.toLanguageId(locale));
994         themeDisplay.setTimeZone(timeZone);
995         themeDisplay.setLookAndFeel(contextPath, theme, colorScheme);
996         themeDisplay.setServerName(req.getServerName());
997         themeDisplay.setServerPort(req.getServerPort());
998         themeDisplay.setSecure(req.isSecure());
999         themeDisplay.setStateExclusive(LiferayWindowState.isExclusive(req));
1000        themeDisplay.setStateMaximized(LiferayWindowState.isMaximized(req));
1001        themeDisplay.setStatePopUp(LiferayWindowState.isPopUp(req));
1002        themeDisplay.setPathApplet(contextPath + "/applets");
1003        themeDisplay.setPathCms(contextPath + "/cms");
1004        themeDisplay.setPathContext(contextPath);
1005        themeDisplay.setPathFlash(contextPath + "/flash");
1006        themeDisplay.setPathFriendlyURLPrivateGroup(
1007            friendlyURLPrivateGroupPath);
1008        themeDisplay.setPathFriendlyURLPrivateUser(friendlyURLPrivateUserPath);
1009        themeDisplay.setPathFriendlyURLPublic(friendlyURLPublicPath);
1010        themeDisplay.setPathImage(imagePath);
1011        themeDisplay.setPathJavaScript(cdnHost + contextPath + "/html/js");
1012        themeDisplay.setPathMain(mainPath);
1013        themeDisplay.setPathSound(contextPath + "/html/sound");
1014
1015        // URLs
1016
1017        themeDisplay.setShowAddContentIcon(false);
1018        themeDisplay.setShowHomeIcon(true);
1019        themeDisplay.setShowMyAccountIcon(signedIn);
1020        themeDisplay.setShowPageSettingsIcon(false);
1021        themeDisplay.setShowPortalIcon(true);
1022        themeDisplay.setShowSignInIcon(!signedIn);
1023        themeDisplay.setShowSignOutIcon(signedIn);
1024
1025        String currentURL = PortalUtil.getCurrentURL(req);
1026
1027        PortletURL createAccountURL = new PortletURLImpl(
1028            req, PortletKeys.MY_ACCOUNT, plid, true);
1029
1030        createAccountURL.setWindowState(WindowState.MAXIMIZED);
1031        createAccountURL.setPortletMode(PortletMode.VIEW);
1032
1033        createAccountURL.setParameter(
1034            "struts_action", "/my_account/create_account");
1035
1036        themeDisplay.setURLCreateAccount(createAccountURL);
1037
1038        themeDisplay.setURLCurrent(currentURL);
1039        themeDisplay.setURLHome(PortalUtil.getPortalURL(req) + contextPath);
1040
1041        if (layout != null) {
1042            if (layout.getType().equals(LayoutImpl.TYPE_PORTLET)) {
1043                boolean freeformLayout =
1044                    layoutTypePortlet.getLayoutTemplateId().equals(
1045                        "freeform");
1046
1047                themeDisplay.setFreeformLayout(freeformLayout);
1048
1049                boolean hasUpdateLayoutPermission =
1050                    LayoutPermissionUtil.contains(
1051                        permissionChecker, layout, ActionKeys.UPDATE);
1052
1053                if (hasUpdateLayoutPermission) {
1054                    if (!LiferayWindowState.isMaximized(req)) {
1055                        themeDisplay.setShowAddContentIcon(true);
1056                    }
1057
1058                    themeDisplay.setShowLayoutTemplatesIcon(true);
1059
1060                    themeDisplay.setURLAddContent(
1061                        "LayoutConfiguration.toggle('" + plid + "', '" +
1062                            PortletKeys.LAYOUT_CONFIGURATION + "', '" +
1063                                doAsUserId + "');");
1064
1065                    themeDisplay.setURLLayoutTemplates(
1066                        "showLayoutTemplates();");
1067                }
1068            }
1069
1070            boolean hasManageLayoutsPermission =
1071                GroupPermissionUtil.contains(
1072                    permissionChecker, portletGroupId,
1073                    ActionKeys.MANAGE_LAYOUTS);
1074
1075            if (hasManageLayoutsPermission) {
1076                themeDisplay.setShowPageSettingsIcon(true);
1077
1078                PortletURL pageSettingsURL = new PortletURLImpl(
1079                    req, PortletKeys.LAYOUT_MANAGEMENT, plid, false);
1080
1081                pageSettingsURL.setWindowState(WindowState.MAXIMIZED);
1082                pageSettingsURL.setPortletMode(PortletMode.VIEW);
1083
1084                pageSettingsURL.setParameter(
1085                    "struts_action", "/layout_management/edit_pages");
1086
1087                if (layout.isPrivateLayout()) {
1088                    pageSettingsURL.setParameter("tabs2", "private");
1089                }
1090                else {
1091                    pageSettingsURL.setParameter("tabs2", "public");
1092                }
1093
1094                pageSettingsURL.setParameter("redirect", currentURL);
1095                pageSettingsURL.setParameter(
1096                    "groupId", String.valueOf(portletGroupId));
1097                pageSettingsURL.setParameter("selPlid", String.valueOf(plid));
1098
1099                themeDisplay.setURLPageSettings(pageSettingsURL);
1100            }
1101
1102            String myAccountNamespace = PortalUtil.getPortletNamespace(
1103                PortletKeys.MY_ACCOUNT);
1104
1105            String myAccountRedirect = ParamUtil.getString(
1106                req, myAccountNamespace + "backURL", currentURL);
1107
1108            PortletURL myAccountURL = new PortletURLImpl(
1109                req, PortletKeys.MY_ACCOUNT, plid, false);
1110
1111            myAccountURL.setWindowState(WindowState.MAXIMIZED);
1112            myAccountURL.setPortletMode(PortletMode.VIEW);
1113
1114            myAccountURL.setParameter("struts_action", "/my_account/edit_user");
1115            myAccountURL.setParameter("backURL", myAccountRedirect);
1116
1117            themeDisplay.setURLMyAccount(myAccountURL);
1118        }
1119
1120        boolean termsOfUseRequired = GetterUtil.getBoolean(
1121            PropsUtil.get(PropsUtil.TERMS_OF_USE_REQUIRED), true);
1122
1123        if (!user.isActive() ||
1124            (termsOfUseRequired && !user.isAgreedToTermsOfUse())) {
1125
1126            themeDisplay.setShowAddContentIcon(false);
1127            themeDisplay.setShowMyAccountIcon(false);
1128            themeDisplay.setShowPageSettingsIcon(false);
1129        }
1130
1131        themeDisplay.setURLPortal(themeDisplay.getURLHome());
1132        themeDisplay.setURLSignIn(mainPath + "/portal/login");
1133        themeDisplay.setURLSignOut(mainPath + "/portal/logout");
1134
1135        PortletURL updateManagerURL = new PortletURLImpl(
1136            req, PortletKeys.UPDATE_MANAGER, plid, false);
1137
1138        updateManagerURL.setWindowState(WindowState.MAXIMIZED);
1139        updateManagerURL.setPortletMode(PortletMode.VIEW);
1140
1141        updateManagerURL.setParameter("struts_action", "/update_manager/view");
1142
1143        themeDisplay.setURLUpdateManager(updateManagerURL);
1144
1145        req.setAttribute(WebKeys.THEME_DISPLAY, themeDisplay);
1146
1147        // Parallel render
1148
1149        boolean parallelRenderEnable = true;
1150
1151        if (layout != null) {
1152            if (layoutTypePortlet.getPortletIds().size() == 1) {
1153                parallelRenderEnable = false;
1154            }
1155        }
1156
1157        Boolean parallelRenderEnableObj = Boolean.valueOf(
1158            ParamUtil.getBoolean(req, "p_p_parallel", parallelRenderEnable));
1159
1160        req.setAttribute(
1161            WebKeys.PORTLET_PARALLEL_RENDER, parallelRenderEnableObj);
1162
1163        // Fix state
1164
1165        fixState(req, themeDisplay);
1166    }
1167
1168    private static final String _PATH_PORTAL_LAYOUT = "/portal/layout";
1169
1170    private static Log _log = LogFactory.getLog(ServicePreAction.class);
1171
1172}