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