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