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