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