1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   *
12   * 
13   */
14  
15  package com.liferay.portal.model.impl;
16  
17  import com.liferay.portal.LayoutFriendlyURLException;
18  import com.liferay.portal.NoSuchGroupException;
19  import com.liferay.portal.PortalException;
20  import com.liferay.portal.SystemException;
21  import com.liferay.portal.kernel.log.Log;
22  import com.liferay.portal.kernel.log.LogFactoryUtil;
23  import com.liferay.portal.kernel.util.CharPool;
24  import com.liferay.portal.kernel.util.HttpUtil;
25  import com.liferay.portal.kernel.util.ListUtil;
26  import com.liferay.portal.kernel.util.LocaleUtil;
27  import com.liferay.portal.kernel.util.LocalizationUtil;
28  import com.liferay.portal.kernel.util.PropsKeys;
29  import com.liferay.portal.kernel.util.StringPool;
30  import com.liferay.portal.kernel.util.StringUtil;
31  import com.liferay.portal.kernel.util.UnicodeProperties;
32  import com.liferay.portal.kernel.util.Validator;
33  import com.liferay.portal.model.ColorScheme;
34  import com.liferay.portal.model.Group;
35  import com.liferay.portal.model.Layout;
36  import com.liferay.portal.model.LayoutConstants;
37  import com.liferay.portal.model.LayoutSet;
38  import com.liferay.portal.model.LayoutType;
39  import com.liferay.portal.model.LayoutTypePortlet;
40  import com.liferay.portal.model.Theme;
41  import com.liferay.portal.security.permission.ActionKeys;
42  import com.liferay.portal.security.permission.PermissionChecker;
43  import com.liferay.portal.service.GroupLocalServiceUtil;
44  import com.liferay.portal.service.LayoutLocalServiceUtil;
45  import com.liferay.portal.service.LayoutSetLocalServiceUtil;
46  import com.liferay.portal.service.ThemeLocalServiceUtil;
47  import com.liferay.portal.service.permission.LayoutPermissionUtil;
48  import com.liferay.portal.theme.ThemeDisplay;
49  import com.liferay.portal.util.CookieKeys;
50  import com.liferay.portal.util.LayoutClone;
51  import com.liferay.portal.util.LayoutCloneFactory;
52  import com.liferay.portal.util.PortalUtil;
53  import com.liferay.portal.util.PropsUtil;
54  import com.liferay.portal.util.PropsValues;
55  import com.liferay.portal.util.WebKeys;
56  import com.liferay.portlet.PortletURLImpl;
57  
58  import java.io.IOException;
59  
60  import java.util.ArrayList;
61  import java.util.Iterator;
62  import java.util.List;
63  import java.util.Locale;
64  
65  import javax.portlet.PortletException;
66  import javax.portlet.PortletMode;
67  import javax.portlet.PortletRequest;
68  import javax.portlet.WindowState;
69  
70  import javax.servlet.http.HttpServletRequest;
71  
72  /**
73   * <a href="LayoutImpl.java.html"><b><i>View Source</i></b></a>
74   *
75   * @author Brian Wing Shun Chan
76   */
77  public class LayoutImpl extends LayoutModelImpl implements Layout {
78  
79      public static int validateFriendlyURL(String friendlyURL) {
80          if (friendlyURL.length() < 2) {
81              return LayoutFriendlyURLException.TOO_SHORT;
82          }
83  
84          if (!friendlyURL.startsWith(StringPool.SLASH)) {
85              return LayoutFriendlyURLException.DOES_NOT_START_WITH_SLASH;
86          }
87  
88          if (friendlyURL.endsWith(StringPool.SLASH)) {
89              return LayoutFriendlyURLException.ENDS_WITH_SLASH;
90          }
91  
92          if (friendlyURL.indexOf(StringPool.DOUBLE_SLASH) != -1) {
93              return LayoutFriendlyURLException.ADJACENT_SLASHES;
94          }
95  
96          for (char c : friendlyURL.toCharArray()) {
97              if ((!Validator.isChar(c)) && (!Validator.isDigit(c)) &&
98                  (c != CharPool.DASH) && (c != CharPool.PERCENT) &&
99                  (c != CharPool.PERIOD)  && (c != CharPool.PLUS) &&
100                 (c != CharPool.SLASH) && (c != CharPool.UNDERLINE)) {
101 
102                 return LayoutFriendlyURLException.INVALID_CHARACTERS;
103             }
104         }
105 
106         return -1;
107     }
108 
109     public static void validateFriendlyURLKeyword(String friendlyURL)
110         throws LayoutFriendlyURLException {
111 
112         String[] keywords = PropsUtil.getArray(
113             PropsKeys.LAYOUT_FRIENDLY_URL_KEYWORDS);
114 
115         for (int i = 0; i < keywords.length; i++) {
116             String keyword = keywords[i];
117 
118             if ((friendlyURL.indexOf(
119                     StringPool.SLASH + keyword + StringPool.SLASH) != -1) ||
120                 (friendlyURL.endsWith(StringPool.SLASH + keyword))) {
121 
122                 LayoutFriendlyURLException lfurle =
123                     new LayoutFriendlyURLException(
124                         LayoutFriendlyURLException.KEYWORD_CONFLICT);
125 
126                 lfurle.setKeywordConflict(keyword);
127 
128                 throw lfurle;
129             }
130         }
131     }
132 
133     public LayoutImpl() {
134     }
135 
136     public List<Layout> getAllChildren() throws SystemException {
137         List<Layout> layouts = new ArrayList<Layout>();
138 
139         Iterator<Layout> itr = getChildren().iterator();
140 
141         while (itr.hasNext()) {
142             Layout layout = itr.next();
143 
144             layouts.add(layout);
145             layouts.addAll(layout.getChildren());
146         }
147 
148         return layouts;
149     }
150 
151     public long getAncestorLayoutId() {
152         long layoutId = 0;
153 
154         try {
155             Layout layout = this;
156 
157             while (true) {
158                 if (!layout.isRootLayout()) {
159                     layout = LayoutLocalServiceUtil.getLayout(
160                         layout.getGroupId(), layout.isPrivateLayout(),
161                         layout.getParentLayoutId());
162                 }
163                 else {
164                     layoutId = layout.getLayoutId();
165 
166                     break;
167                 }
168             }
169         }
170         catch (Exception e) {
171             _log.error(e, e);
172         }
173 
174         return layoutId;
175     }
176 
177     public long getAncestorPlid() {
178         long plid = 0;
179 
180         try {
181             Layout layout = this;
182 
183             while (true) {
184                 if (!layout.isRootLayout()) {
185                     layout = LayoutLocalServiceUtil.getLayout(
186                         layout.getGroupId(), layout.isPrivateLayout(),
187                         layout.getParentLayoutId());
188                 }
189                 else {
190                     plid = layout.getPlid();
191 
192                     break;
193                 }
194             }
195         }
196         catch (Exception e) {
197             _log.error(e, e);
198         }
199 
200         return plid;
201     }
202 
203     public List<Layout> getAncestors() throws PortalException, SystemException {
204         List<Layout> layouts = new ArrayList<Layout>();
205 
206         Layout layout = this;
207 
208         while (true) {
209             if (!layout.isRootLayout()) {
210                 layout = LayoutLocalServiceUtil.getLayout(
211                     layout.getGroupId(), layout.isPrivateLayout(),
212                     layout.getParentLayoutId());
213 
214                 layouts.add(layout);
215             }
216             else {
217                 break;
218             }
219         }
220 
221         return layouts;
222     }
223 
224     public List<Layout> getChildren() throws SystemException {
225         return LayoutLocalServiceUtil.getLayouts(
226             getGroupId(), isPrivateLayout(), getLayoutId());
227     }
228 
229     public List<Layout> getChildren(PermissionChecker permissionChecker)
230         throws PortalException, SystemException {
231 
232         List<Layout> layouts = ListUtil.copy(getChildren());
233 
234         Iterator<Layout> itr = layouts.iterator();
235 
236         while (itr.hasNext()) {
237             Layout layout = itr.next();
238 
239             if (layout.isHidden() ||
240                 !LayoutPermissionUtil.contains(
241                     permissionChecker, layout, ActionKeys.VIEW)) {
242 
243                 itr.remove();
244             }
245         }
246 
247         return layouts;
248     }
249 
250     public ColorScheme getColorScheme() throws SystemException {
251         if (isInheritLookAndFeel()) {
252             return getLayoutSet().getColorScheme();
253         }
254         else {
255             return ThemeLocalServiceUtil.getColorScheme(
256                 getCompanyId(), getTheme().getThemeId(), getColorSchemeId(),
257                 false);
258         }
259     }
260 
261     public String getCssText() {
262         if (isInheritLookAndFeel()) {
263             return getLayoutSet().getCss();
264         }
265         else {
266             return getCss();
267         }
268     }
269 
270     public Group getGroup() {
271         Group group = null;
272 
273         try {
274             group = GroupLocalServiceUtil.getGroup(getGroupId());
275         }
276         catch (Exception e) {
277             group = new GroupImpl();
278 
279             _log.error(e, e);
280         }
281 
282         return group;
283     }
284 
285     public String getHTMLTitle(Locale locale) {
286         String localeLanguageId = LocaleUtil.toLanguageId(locale);
287 
288         return getHTMLTitle(localeLanguageId);
289     }
290 
291     public String getHTMLTitle(String localeLanguageId) {
292         String htmlTitle = getTitle(localeLanguageId);
293 
294         if (Validator.isNull(htmlTitle)) {
295             htmlTitle = getName(localeLanguageId);
296         }
297 
298         return htmlTitle;
299     }
300 
301     public LayoutSet getLayoutSet() {
302         LayoutSet layoutSet = null;
303 
304         try {
305             layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
306                 getGroupId(), isPrivateLayout());
307         }
308         catch (Exception e) {
309             layoutSet = new LayoutSetImpl();
310 
311             _log.error(e, e);
312         }
313 
314         return layoutSet;
315     }
316 
317     public LayoutType getLayoutType() {
318         return new LayoutTypePortletImpl(this);
319     }
320 
321     public String getName(Locale locale) {
322         String localeLanguageId = LocaleUtil.toLanguageId(locale);
323 
324         return getName(localeLanguageId);
325     }
326 
327     public String getName(Locale locale, boolean useDefault) {
328         String localeLanguageId = LocaleUtil.toLanguageId(locale);
329 
330         return getName(localeLanguageId, useDefault);
331     }
332 
333     public String getName(String localeLanguageId) {
334         return LocalizationUtil.getLocalization(getName(), localeLanguageId);
335     }
336 
337     public String getName(String localeLanguageId, boolean useDefault) {
338         return LocalizationUtil.getLocalization(
339             getName(), localeLanguageId, useDefault);
340     }
341 
342     public String getRegularURL(HttpServletRequest request)
343         throws SystemException {
344 
345         return _getURL(request, false, false);
346     }
347 
348     public String getResetLayoutURL(HttpServletRequest request)
349         throws SystemException {
350 
351         return _getURL(request, true, true);
352     }
353 
354     public String getResetMaxStateURL(HttpServletRequest request)
355         throws SystemException {
356 
357         return _getURL(request, true, false);
358     }
359 
360     public Group getScopeGroup() throws PortalException, SystemException {
361         Group group = null;
362 
363         try {
364             group = GroupLocalServiceUtil.getLayoutGroup(
365                 getCompanyId(), getPlid());
366         }
367         catch (NoSuchGroupException nsge) {
368         }
369 
370         return group;
371     }
372 
373     public String getTarget() {
374         return PortalUtil.getLayoutTarget(this);
375     }
376 
377     public Theme getTheme() throws SystemException {
378         if (isInheritLookAndFeel()) {
379             return getLayoutSet().getTheme();
380         }
381         else {
382             return ThemeLocalServiceUtil.getTheme(
383                 getCompanyId(), getThemeId(), false);
384         }
385     }
386 
387     public String getTitle(Locale locale) {
388         String localeLanguageId = LocaleUtil.toLanguageId(locale);
389 
390         return getTitle(localeLanguageId);
391     }
392 
393     public String getTitle(Locale locale, boolean useDefault) {
394         String localeLanguageId = LocaleUtil.toLanguageId(locale);
395 
396         return getTitle(localeLanguageId, useDefault);
397     }
398 
399     public String getTitle(String localeLanguageId) {
400         return LocalizationUtil.getLocalization(getTitle(), localeLanguageId);
401     }
402 
403     public String getTitle(String localeLanguageId, boolean useDefault) {
404         return LocalizationUtil.getLocalization(
405             getTitle(), localeLanguageId, useDefault);
406     }
407 
408     public String getTypeSettings() {
409         if (_typeSettingsProperties == null) {
410             return super.getTypeSettings();
411         }
412         else {
413             return _typeSettingsProperties.toString();
414         }
415     }
416 
417     public UnicodeProperties getTypeSettingsProperties() {
418         if (_typeSettingsProperties == null) {
419             _typeSettingsProperties = new UnicodeProperties(true);
420 
421             _typeSettingsProperties.fastLoad(super.getTypeSettings());
422         }
423 
424         return _typeSettingsProperties;
425     }
426 
427     public ColorScheme getWapColorScheme() throws SystemException {
428         if (isInheritLookAndFeel()) {
429             return getLayoutSet().getWapColorScheme();
430         }
431         else {
432             return ThemeLocalServiceUtil.getColorScheme(
433                 getCompanyId(), getWapTheme().getThemeId(),
434                 getWapColorSchemeId(), true);
435         }
436     }
437 
438     public Theme getWapTheme() throws SystemException {
439         if (isInheritWapLookAndFeel()) {
440             return getLayoutSet().getWapTheme();
441         }
442         else {
443             return ThemeLocalServiceUtil.getTheme(
444                 getCompanyId(), getWapThemeId(), true);
445         }
446     }
447 
448     public boolean hasAncestor(long layoutId)
449         throws PortalException, SystemException {
450 
451         long parentLayoutId = getParentLayoutId();
452 
453         while (isRootLayout()) {
454             if (parentLayoutId == layoutId) {
455                 return true;
456             }
457             else {
458                 Layout parentLayout = LayoutLocalServiceUtil.getLayout(
459                     getGroupId(), isPrivateLayout(), parentLayoutId);
460 
461                 parentLayoutId = parentLayout.getParentLayoutId();
462             }
463         }
464 
465         return false;
466     }
467 
468     public boolean hasScopeGroup() throws PortalException, SystemException {
469         Group group = getScopeGroup();
470 
471         if (group != null) {
472             return true;
473         }
474         else {
475             return false;
476         }
477     }
478 
479     public boolean isChildSelected(boolean selectable, Layout layout) {
480         if (selectable) {
481             long plid = getPlid();
482 
483             try {
484                 List<Layout> ancestors = layout.getAncestors();
485 
486                 for (Layout curLayout : ancestors) {
487                     if (plid == curLayout.getPlid()) {
488                         return true;
489                     }
490                 }
491             }
492             catch (Exception e) {
493                 _log.error(e, e);
494             }
495         }
496 
497         return false;
498     }
499 
500     public boolean isFirstChild() {
501         if (getPriority() == 0) {
502             return true;
503         }
504         else {
505             return false;
506         }
507     }
508 
509     public boolean isFirstParent() {
510         if (isFirstChild() && isRootLayout()) {
511             return true;
512         }
513         else {
514             return false;
515         }
516     }
517 
518     public boolean isInheritLookAndFeel() {
519         if (Validator.isNull(getThemeId()) ||
520             Validator.isNull(getColorSchemeId())) {
521 
522             return true;
523         }
524         else {
525             return false;
526         }
527     }
528 
529     public boolean isInheritWapLookAndFeel() {
530         if (Validator.isNull(getWapThemeId()) ||
531             Validator.isNull(getWapColorSchemeId())) {
532 
533             return true;
534         }
535         else {
536             return false;
537         }
538     }
539 
540     public boolean isPublicLayout() {
541         return !isPrivateLayout();
542     }
543 
544     public boolean isRootLayout() {
545         if (getParentLayoutId() == LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
546             return true;
547         }
548         else {
549             return false;
550         }
551     }
552 
553     public boolean isSelected(
554         boolean selectable, Layout layout, long ancestorPlid) {
555 
556         if (selectable) {
557             long plid = getPlid();
558 
559             if ((plid == layout.getPlid()) || (plid == ancestorPlid)) {
560                 return true;
561             }
562         }
563 
564         return false;
565     }
566 
567     public boolean isTypeArticle() {
568         if (getType().equals(LayoutConstants.TYPE_ARTICLE)) {
569             return true;
570         }
571         else {
572             return false;
573         }
574     }
575 
576     public boolean isTypeControlPanel() {
577         if (getType().equals(LayoutConstants.TYPE_CONTROL_PANEL)) {
578             return true;
579         }
580         else {
581             return false;
582         }
583     }
584 
585     public boolean isTypeEmbedded() {
586         if (getType().equals(LayoutConstants.TYPE_EMBEDDED)) {
587             return true;
588         }
589         else {
590             return false;
591         }
592     }
593 
594     public boolean isTypeLinkToLayout() {
595         if (getType().equals(LayoutConstants.TYPE_LINK_TO_LAYOUT)) {
596             return true;
597         }
598         else {
599             return false;
600         }
601     }
602 
603     public boolean isTypePanel() {
604         if (getType().equals(LayoutConstants.TYPE_PANEL)) {
605             return true;
606         }
607         else {
608             return false;
609         }
610     }
611 
612     public boolean isTypePortlet() {
613         if (getType().equals(LayoutConstants.TYPE_PORTLET)) {
614             return true;
615         }
616         else {
617             return false;
618         }
619     }
620 
621     public boolean isTypeURL() {
622         if (getType().equals(LayoutConstants.TYPE_URL)) {
623             return true;
624         }
625         else {
626             return false;
627         }
628     }
629 
630     public void setName(String name, Locale locale) {
631         String localeLanguageId = LocaleUtil.toLanguageId(locale);
632 
633         if (Validator.isNotNull(name)) {
634             setName(
635                 LocalizationUtil.updateLocalization(
636                     getName(), "name", name, localeLanguageId));
637         }
638         else {
639             setName(
640                 LocalizationUtil.removeLocalization(
641                     getName(), "name", localeLanguageId));
642         }
643     }
644 
645     public void setTitle(String title, Locale locale) {
646         String localeLanguageId = LocaleUtil.toLanguageId(locale);
647 
648         if (Validator.isNotNull(title)) {
649             setTitle(
650                 LocalizationUtil.updateLocalization(
651                     getTitle(), "title", title, localeLanguageId));
652         }
653         else {
654             setTitle(
655                 LocalizationUtil.removeLocalization(
656                     getTitle(), "title", localeLanguageId));
657         }
658     }
659 
660     public void setTypeSettings(String typeSettings) {
661         _typeSettingsProperties = null;
662 
663         super.setTypeSettings(typeSettings);
664     }
665 
666     public void setTypeSettingsProperties(
667         UnicodeProperties typeSettingsProperties) {
668 
669         _typeSettingsProperties = typeSettingsProperties;
670 
671         super.setTypeSettings(_typeSettingsProperties.toString());
672     }
673 
674     private LayoutTypePortlet _getLayoutTypePortletClone(
675             HttpServletRequest request)
676         throws IOException {
677 
678         LayoutTypePortlet layoutTypePortlet = null;
679 
680         LayoutClone layoutClone = LayoutCloneFactory.getInstance();
681 
682         if (layoutClone != null) {
683             String typeSettings = layoutClone.get(request, getPlid());
684 
685             if (typeSettings != null) {
686                 UnicodeProperties props = new UnicodeProperties(true);
687 
688                 props.load(typeSettings);
689 
690                 String stateMax = props.getProperty(
691                     LayoutTypePortletImpl.STATE_MAX);
692                 String stateMin = props.getProperty(
693                     LayoutTypePortletImpl.STATE_MIN);
694 
695                 Layout layout = (Layout)this.clone();
696 
697                 layoutTypePortlet = (LayoutTypePortlet)layout.getLayoutType();
698 
699                 layoutTypePortlet.setStateMax(stateMax);
700                 layoutTypePortlet.setStateMin(stateMin);
701             }
702         }
703 
704         if (layoutTypePortlet == null) {
705             layoutTypePortlet = (LayoutTypePortlet)getLayoutType();
706         }
707 
708         return layoutTypePortlet;
709     }
710 
711     private String _getURL(
712             HttpServletRequest request, boolean resetMaxState,
713             boolean resetRenderParameters)
714         throws SystemException {
715 
716         ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
717             WebKeys.THEME_DISPLAY);
718 
719         if (resetMaxState) {
720             Layout layout = themeDisplay.getLayout();
721 
722             LayoutTypePortlet layoutTypePortlet = null;
723 
724             if (layout.equals(this)) {
725                 layoutTypePortlet = themeDisplay.getLayoutTypePortlet();
726             }
727             else {
728                 try {
729                     layoutTypePortlet = _getLayoutTypePortletClone(request);
730                 }
731                 catch (IOException ioe) {
732                     _log.error("Unable to clone layout settings", ioe);
733 
734                     layoutTypePortlet = (LayoutTypePortlet)getLayoutType();
735                 }
736             }
737 
738             if (layoutTypePortlet.hasStateMax()) {
739                 String portletId =
740                     StringUtil.split(layoutTypePortlet.getStateMax())[0];
741 
742                 PortletURLImpl portletURLImpl = new PortletURLImpl(
743                     request, portletId, getPlid(), PortletRequest.ACTION_PHASE);
744 
745                 try {
746                     portletURLImpl.setWindowState(WindowState.NORMAL);
747                     portletURLImpl.setPortletMode(PortletMode.VIEW);
748                 }
749                 catch (PortletException pe) {
750                     throw new SystemException(pe);
751                 }
752 
753                 portletURLImpl.setAnchor(false);
754 
755                 if (PropsValues.LAYOUT_DEFAULT_P_L_RESET &&
756                     !resetRenderParameters) {
757 
758                     portletURLImpl.setParameter("p_l_reset", "0");
759                 }
760                 else if (!PropsValues.LAYOUT_DEFAULT_P_L_RESET &&
761                          resetRenderParameters) {
762 
763                     portletURLImpl.setParameter("p_l_reset", "1");
764                 }
765 
766                 return portletURLImpl.toString();
767             }
768         }
769 
770         String url = PortalUtil.getLayoutURL(this, themeDisplay);
771 
772         if (!CookieKeys.hasSessionId(request)) {
773             url = PortalUtil.getURLWithSessionId(
774                 url, request.getSession().getId());
775         }
776 
777         if (!resetMaxState && !resetMaxState) {
778             return url;
779         }
780 
781         if (PropsValues.LAYOUT_DEFAULT_P_L_RESET && !resetRenderParameters) {
782             url = HttpUtil.addParameter(url, "p_l_reset", 0);
783         }
784         else if (!PropsValues.LAYOUT_DEFAULT_P_L_RESET &&
785                  resetRenderParameters) {
786 
787             url = HttpUtil.addParameter(url, "p_l_reset", 1);
788         }
789 
790         return url;
791     }
792 
793     private static Log _log = LogFactoryUtil.getLog(LayoutImpl.class);
794 
795     private UnicodeProperties _typeSettingsProperties;
796 
797 }