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