001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
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.PropsKeys;
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.CookieKeys;
050    import com.liferay.portal.util.LayoutClone;
051    import com.liferay.portal.util.LayoutCloneFactory;
052    import com.liferay.portal.util.PortalUtil;
053    import com.liferay.portal.util.PropsUtil;
054    import com.liferay.portal.util.PropsValues;
055    import com.liferay.portal.util.WebKeys;
056    import com.liferay.portlet.PortletURLImpl;
057    
058    import java.io.IOException;
059    
060    import java.util.ArrayList;
061    import java.util.Iterator;
062    import java.util.List;
063    import java.util.Locale;
064    
065    import javax.portlet.PortletException;
066    import javax.portlet.PortletMode;
067    import javax.portlet.PortletRequest;
068    import javax.portlet.WindowState;
069    
070    import javax.servlet.http.HttpServletRequest;
071    
072    /**
073     * @author Brian Wing Shun Chan
074     */
075    public class LayoutImpl extends LayoutBaseImpl {
076    
077            public static int validateFriendlyURL(String friendlyURL) {
078                    if (friendlyURL.length() < 2) {
079                            return LayoutFriendlyURLException.TOO_SHORT;
080                    }
081    
082                    if (friendlyURL.length() > LayoutConstants.FRIENDLY_URL_MAX_LENGTH) {
083                            return LayoutFriendlyURLException.TOO_LONG;
084                    }
085    
086                    if (!friendlyURL.startsWith(StringPool.SLASH)) {
087                            return LayoutFriendlyURLException.DOES_NOT_START_WITH_SLASH;
088                    }
089    
090                    if (friendlyURL.endsWith(StringPool.SLASH)) {
091                            return LayoutFriendlyURLException.ENDS_WITH_SLASH;
092                    }
093    
094                    if (friendlyURL.indexOf(StringPool.DOUBLE_SLASH) != -1) {
095                            return LayoutFriendlyURLException.ADJACENT_SLASHES;
096                    }
097    
098                    for (char c : friendlyURL.toCharArray()) {
099                            if ((!Validator.isChar(c)) && (!Validator.isDigit(c)) &&
100                                    (c != CharPool.DASH) && (c != CharPool.PERCENT) &&
101                                    (c != CharPool.PERIOD)  && (c != CharPool.PLUS) &&
102                                    (c != CharPool.SLASH) && (c != CharPool.STAR) &&
103                                    (c != CharPool.UNDERLINE)) {
104    
105                                    return LayoutFriendlyURLException.INVALID_CHARACTERS;
106                            }
107                    }
108    
109                    return -1;
110            }
111    
112            public static void validateFriendlyURLKeyword(String friendlyURL)
113                    throws LayoutFriendlyURLException {
114    
115                    String[] keywords = PropsUtil.getArray(
116                            PropsKeys.LAYOUT_FRIENDLY_URL_KEYWORDS);
117    
118                    for (String keyword : keywords) {
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() throws PortalException, SystemException {
153                    long layoutId = 0;
154    
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                    return layoutId;
171            }
172    
173            public long getAncestorPlid() throws PortalException, SystemException {
174                    long plid = 0;
175    
176                    Layout layout = this;
177    
178                    while (true) {
179                            if (!layout.isRootLayout()) {
180                                    layout = LayoutLocalServiceUtil.getLayout(
181                                            layout.getGroupId(), layout.isPrivateLayout(),
182                                            layout.getParentLayoutId());
183                            }
184                            else {
185                                    plid = layout.getPlid();
186    
187                                    break;
188                            }
189                    }
190    
191                    return plid;
192            }
193    
194            public List<Layout> getAncestors() throws PortalException, SystemException {
195                    List<Layout> layouts = new ArrayList<Layout>();
196    
197                    Layout layout = this;
198    
199                    while (true) {
200                            if (!layout.isRootLayout()) {
201                                    layout = LayoutLocalServiceUtil.getLayout(
202                                            layout.getGroupId(), layout.isPrivateLayout(),
203                                            layout.getParentLayoutId());
204    
205                                    layouts.add(layout);
206                            }
207                            else {
208                                    break;
209                            }
210                    }
211    
212                    return layouts;
213            }
214    
215            public List<Layout> getChildren() throws SystemException {
216                    return LayoutLocalServiceUtil.getLayouts(
217                            getGroupId(), isPrivateLayout(), getLayoutId());
218            }
219    
220            public List<Layout> getChildren(PermissionChecker permissionChecker)
221                    throws PortalException, SystemException {
222    
223                    List<Layout> layouts = ListUtil.copy(getChildren());
224    
225                    Iterator<Layout> itr = layouts.iterator();
226    
227                    while (itr.hasNext()) {
228                            Layout layout = itr.next();
229    
230                            if (layout.isHidden() ||
231                                    !LayoutPermissionUtil.contains(
232                                            permissionChecker, layout, ActionKeys.VIEW)) {
233    
234                                    itr.remove();
235                            }
236                    }
237    
238                    return layouts;
239            }
240    
241            public ColorScheme getColorScheme()
242                    throws PortalException, SystemException {
243    
244                    if (isInheritLookAndFeel()) {
245                            return getLayoutSet().getColorScheme();
246                    }
247                    else {
248                            return ThemeLocalServiceUtil.getColorScheme(
249                                    getCompanyId(), getTheme().getThemeId(), getColorSchemeId(),
250                                    false);
251                    }
252            }
253    
254            public String getCssText() throws PortalException, SystemException {
255                    if (isInheritLookAndFeel()) {
256                            return getLayoutSet().getCss();
257                    }
258                    else {
259                            return getCss();
260                    }
261            }
262    
263            public Group getGroup() throws PortalException, SystemException {
264                    return GroupLocalServiceUtil.getGroup(getGroupId());
265            }
266    
267            public String getHTMLTitle(Locale locale) {
268                    String localeLanguageId = LocaleUtil.toLanguageId(locale);
269    
270                    return getHTMLTitle(localeLanguageId);
271            }
272    
273            public String getHTMLTitle(String localeLanguageId) {
274                    String htmlTitle = getTitle(localeLanguageId);
275    
276                    if (Validator.isNull(htmlTitle)) {
277                            htmlTitle = getName(localeLanguageId);
278                    }
279    
280                    return htmlTitle;
281            }
282    
283            public LayoutSet getLayoutSet() throws PortalException, SystemException {
284                    if (_layoutSet == null) {
285                            _layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
286                                    getGroupId(), isPrivateLayout());
287                    }
288    
289                    return _layoutSet;
290            }
291    
292            public LayoutType getLayoutType() {
293                    if (_layoutType == null) {
294                            _layoutType = new LayoutTypePortletImpl(this);
295                    }
296    
297                    return _layoutType;
298            }
299    
300            public long getParentPlid() throws PortalException, SystemException {
301                    if (getParentLayoutId() == LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
302                            return 0;
303                    }
304    
305                    Layout layout = LayoutLocalServiceUtil.getLayout(
306                            getGroupId(), isPrivateLayout(), getParentLayoutId());
307    
308                    return layout.getPlid();
309            }
310    
311            public String getRegularURL(HttpServletRequest request)
312                    throws PortalException, SystemException {
313    
314                    return _getURL(request, false, false);
315            }
316    
317            public String getResetLayoutURL(HttpServletRequest request)
318                    throws PortalException, SystemException {
319    
320                    return _getURL(request, true, true);
321            }
322    
323            public String getResetMaxStateURL(HttpServletRequest request)
324                    throws PortalException, SystemException {
325    
326                    return _getURL(request, true, false);
327            }
328    
329            public Group getScopeGroup() throws PortalException, SystemException {
330                    Group group = null;
331    
332                    try {
333                            group = GroupLocalServiceUtil.getLayoutGroup(
334                                    getCompanyId(), getPlid());
335                    }
336                    catch (NoSuchGroupException nsge) {
337                    }
338    
339                    return group;
340            }
341    
342            public String getTarget() {
343                    return PortalUtil.getLayoutTarget(this);
344            }
345    
346            public Theme getTheme() throws PortalException, SystemException {
347                    if (isInheritLookAndFeel()) {
348                            return getLayoutSet().getTheme();
349                    }
350                    else {
351                            return ThemeLocalServiceUtil.getTheme(
352                                    getCompanyId(), getThemeId(), false);
353                    }
354            }
355    
356            public String getThemeSetting(String key, String device) {
357                    UnicodeProperties typeSettingsProperties = getTypeSettingsProperties();
358    
359                    String value = typeSettingsProperties.getProperty(
360                            ThemeSettingImpl.namespaceProperty(device, key));
361    
362                    if (value != null) {
363                            return value;
364                    }
365    
366                    try {
367                            LayoutSet layoutSet = getLayoutSet();
368    
369                            value = layoutSet.getThemeSetting(key, device);
370                    }
371                    catch (Exception e) {
372                    }
373    
374                    return value;
375            }
376    
377            @Override
378            public String getTypeSettings() {
379                    if (_typeSettingsProperties == null) {
380                            return super.getTypeSettings();
381                    }
382                    else {
383                            return _typeSettingsProperties.toString();
384                    }
385            }
386    
387            public UnicodeProperties getTypeSettingsProperties() {
388                    if (_typeSettingsProperties == null) {
389                            _typeSettingsProperties = new UnicodeProperties(true);
390    
391                            _typeSettingsProperties.fastLoad(super.getTypeSettings());
392                    }
393    
394                    return _typeSettingsProperties;
395            }
396    
397            public String getTypeSettingsProperty(String key) {
398                    UnicodeProperties typeSettingsProperties = getTypeSettingsProperties();
399    
400                    return typeSettingsProperties.getProperty(key);
401            }
402    
403            public ColorScheme getWapColorScheme()
404                    throws PortalException, SystemException {
405    
406                    if (isInheritLookAndFeel()) {
407                            return getLayoutSet().getWapColorScheme();
408                    }
409                    else {
410                            return ThemeLocalServiceUtil.getColorScheme(
411                                    getCompanyId(), getWapTheme().getThemeId(),
412                                    getWapColorSchemeId(), true);
413                    }
414            }
415    
416            public Theme getWapTheme() throws PortalException, SystemException {
417                    if (isInheritWapLookAndFeel()) {
418                            return getLayoutSet().getWapTheme();
419                    }
420                    else {
421                            return ThemeLocalServiceUtil.getTheme(
422                                    getCompanyId(), getWapThemeId(), true);
423                    }
424            }
425    
426            public boolean hasAncestor(long layoutId)
427                    throws PortalException, SystemException {
428    
429                    long parentLayoutId = getParentLayoutId();
430    
431                    while (parentLayoutId != LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
432                            if (parentLayoutId == layoutId) {
433                                    return true;
434                            }
435                            else {
436                                    Layout parentLayout = LayoutLocalServiceUtil.getLayout(
437                                            getGroupId(), isPrivateLayout(), parentLayoutId);
438    
439                                    parentLayoutId = parentLayout.getParentLayoutId();
440                            }
441                    }
442    
443                    return false;
444            }
445    
446            public boolean hasChildren() throws SystemException {
447                    return LayoutLocalServiceUtil.hasLayouts(
448                            getGroupId(), isPrivateLayout(), getLayoutId());
449            }
450    
451            public boolean hasScopeGroup() throws PortalException, SystemException {
452                    Group group = getScopeGroup();
453    
454                    if (group != null) {
455                            return true;
456                    }
457                    else {
458                            return false;
459                    }
460            }
461    
462            public boolean isChildSelected(boolean selectable, Layout layout)
463                    throws PortalException, SystemException {
464    
465                    if (selectable) {
466                            long plid = getPlid();
467    
468                            List<Layout> ancestors = layout.getAncestors();
469    
470                            for (Layout curLayout : ancestors) {
471                                    if (plid == curLayout.getPlid()) {
472                                            return true;
473                                    }
474                            }
475                    }
476    
477                    return false;
478            }
479    
480            public boolean isContentDisplayPage() {
481                    UnicodeProperties typeSettingsProperties = getTypeSettingsProperties();
482    
483                    String defaultAssetPublisherPortletId =
484                            typeSettingsProperties.getProperty(
485                                    LayoutTypePortletConstants.DEFAULT_ASSET_PUBLISHER_PORTLET_ID);
486    
487                    if (Validator.isNotNull(defaultAssetPublisherPortletId)) {
488                            return true;
489                    }
490                    else {
491                            return false;
492                    }
493            }
494    
495            public boolean isFirstChild() {
496                    if (getPriority() == 0) {
497                            return true;
498                    }
499                    else {
500                            return false;
501                    }
502            }
503    
504            public boolean isFirstParent() {
505                    if (isFirstChild() && isRootLayout()) {
506                            return true;
507                    }
508                    else {
509                            return false;
510                    }
511            }
512    
513            public boolean isInheritLookAndFeel() {
514                    if (Validator.isNull(getThemeId()) ||
515                            Validator.isNull(getColorSchemeId())) {
516    
517                            return true;
518                    }
519                    else {
520                            return false;
521                    }
522            }
523    
524            public boolean isInheritWapLookAndFeel() {
525                    if (Validator.isNull(getWapThemeId()) ||
526                            Validator.isNull(getWapColorSchemeId())) {
527    
528                            return true;
529                    }
530                    else {
531                            return false;
532                    }
533            }
534    
535            public boolean isPublicLayout() {
536                    return !isPrivateLayout();
537            }
538    
539            public boolean isRootLayout() {
540                    if (getParentLayoutId() == LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
541                            return true;
542                    }
543                    else {
544                            return false;
545                    }
546            }
547    
548            public boolean isSelected(
549                    boolean selectable, Layout layout, long ancestorPlid) {
550    
551                    if (selectable) {
552                            long plid = getPlid();
553    
554                            if ((plid == layout.getPlid()) || (plid == ancestorPlid)) {
555                                    return true;
556                            }
557                    }
558    
559                    return false;
560            }
561    
562            public boolean isTypeArticle() {
563                    if (getType().equals(LayoutConstants.TYPE_ARTICLE)) {
564                            return true;
565                    }
566                    else {
567                            return false;
568                    }
569            }
570    
571            public boolean isTypeControlPanel() {
572                    if (getType().equals(LayoutConstants.TYPE_CONTROL_PANEL)) {
573                            return true;
574                    }
575                    else {
576                            return false;
577                    }
578            }
579    
580            public boolean isTypeEmbedded() {
581                    if (getType().equals(LayoutConstants.TYPE_EMBEDDED)) {
582                            return true;
583                    }
584                    else {
585                            return false;
586                    }
587            }
588    
589            public boolean isTypeLinkToLayout() {
590                    if (getType().equals(LayoutConstants.TYPE_LINK_TO_LAYOUT)) {
591                            return true;
592                    }
593                    else {
594                            return false;
595                    }
596            }
597    
598            public boolean isTypePanel() {
599                    if (getType().equals(LayoutConstants.TYPE_PANEL)) {
600                            return true;
601                    }
602                    else {
603                            return false;
604                    }
605            }
606    
607            public boolean isTypePortlet() {
608                    if (getType().equals(LayoutConstants.TYPE_PORTLET)) {
609                            return true;
610                    }
611                    else {
612                            return false;
613                    }
614            }
615    
616            public boolean isTypeURL() {
617                    if (getType().equals(LayoutConstants.TYPE_URL)) {
618                            return true;
619                    }
620                    else {
621                            return false;
622                    }
623            }
624    
625            @Override
626            public void setGroupId(long groupId) {
627                    super.setGroupId(groupId);
628    
629                    _layoutSet = null;
630            }
631    
632            public void setLayoutSet(LayoutSet layoutSet) {
633                    _layoutSet = layoutSet;
634            }
635    
636            @Override
637            public void setPrivateLayout(boolean privateLayout) {
638                    super.setPrivateLayout(privateLayout);
639    
640                    _layoutSet = null;
641            }
642    
643            @Override
644            public void setTypeSettings(String typeSettings) {
645                    _typeSettingsProperties = null;
646    
647                    super.setTypeSettings(typeSettings);
648            }
649    
650            public void setTypeSettingsProperties(
651                    UnicodeProperties typeSettingsProperties) {
652    
653                    _typeSettingsProperties = typeSettingsProperties;
654    
655                    super.setTypeSettings(_typeSettingsProperties.toString());
656            }
657    
658            private LayoutTypePortlet _getLayoutTypePortletClone(
659                            HttpServletRequest request)
660                    throws IOException {
661    
662                    LayoutTypePortlet layoutTypePortlet = null;
663    
664                    LayoutClone layoutClone = LayoutCloneFactory.getInstance();
665    
666                    if (layoutClone != null) {
667                            String typeSettings = layoutClone.get(request, getPlid());
668    
669                            if (typeSettings != null) {
670                                    UnicodeProperties typeSettingsProperties =
671                                            new UnicodeProperties(true);
672    
673                                    typeSettingsProperties.load(typeSettings);
674    
675                                    String stateMax = typeSettingsProperties.getProperty(
676                                            LayoutTypePortletConstants.STATE_MAX);
677                                    String stateMin = typeSettingsProperties.getProperty(
678                                            LayoutTypePortletConstants.STATE_MIN);
679    
680                                    Layout layout = (Layout)this.clone();
681    
682                                    layoutTypePortlet = (LayoutTypePortlet)layout.getLayoutType();
683    
684                                    layoutTypePortlet.setStateMax(stateMax);
685                                    layoutTypePortlet.setStateMin(stateMin);
686                            }
687                    }
688    
689                    if (layoutTypePortlet == null) {
690                            layoutTypePortlet = (LayoutTypePortlet)getLayoutType();
691                    }
692    
693                    return layoutTypePortlet;
694            }
695    
696            private String _getURL(
697                            HttpServletRequest request, boolean resetMaxState,
698                            boolean resetRenderParameters)
699                    throws PortalException, SystemException {
700    
701                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
702                            WebKeys.THEME_DISPLAY);
703    
704                    if (resetMaxState) {
705                            Layout layout = themeDisplay.getLayout();
706    
707                            LayoutTypePortlet layoutTypePortlet = null;
708    
709                            if (layout.equals(this)) {
710                                    layoutTypePortlet = themeDisplay.getLayoutTypePortlet();
711                            }
712                            else {
713                                    try {
714                                            layoutTypePortlet = _getLayoutTypePortletClone(request);
715                                    }
716                                    catch (IOException ioe) {
717                                            _log.error("Unable to clone layout settings", ioe);
718    
719                                            layoutTypePortlet = (LayoutTypePortlet)getLayoutType();
720                                    }
721                            }
722    
723                            if (layoutTypePortlet.hasStateMax()) {
724                                    String portletId =
725                                            StringUtil.split(layoutTypePortlet.getStateMax())[0];
726    
727                                    PortletURLImpl portletURLImpl = new PortletURLImpl(
728                                            request, portletId, getPlid(), PortletRequest.ACTION_PHASE);
729    
730                                    try {
731                                            portletURLImpl.setWindowState(WindowState.NORMAL);
732                                            portletURLImpl.setPortletMode(PortletMode.VIEW);
733                                    }
734                                    catch (PortletException pe) {
735                                            throw new SystemException(pe);
736                                    }
737    
738                                    portletURLImpl.setAnchor(false);
739    
740                                    if (PropsValues.LAYOUT_DEFAULT_P_L_RESET &&
741                                            !resetRenderParameters) {
742    
743                                            portletURLImpl.setParameter("p_l_reset", "0");
744                                    }
745                                    else if (!PropsValues.LAYOUT_DEFAULT_P_L_RESET &&
746                                                     resetRenderParameters) {
747    
748                                            portletURLImpl.setParameter("p_l_reset", "1");
749                                    }
750    
751                                    return portletURLImpl.toString();
752                            }
753                    }
754    
755                    String url = PortalUtil.getLayoutURL(this, themeDisplay);
756    
757                    if (!CookieKeys.hasSessionId(request)) {
758                            url = PortalUtil.getURLWithSessionId(
759                                    url, request.getSession().getId());
760                    }
761    
762                    if (!resetMaxState) {
763                            return url;
764                    }
765    
766                    if (PropsValues.LAYOUT_DEFAULT_P_L_RESET && !resetRenderParameters) {
767                            url = HttpUtil.addParameter(url, "p_l_reset", 0);
768                    }
769                    else if (!PropsValues.LAYOUT_DEFAULT_P_L_RESET &&
770                                     resetRenderParameters) {
771    
772                            url = HttpUtil.addParameter(url, "p_l_reset", 1);
773                    }
774    
775                    return url;
776            }
777    
778            private static Log _log = LogFactoryUtil.getLog(LayoutImpl.class);
779    
780            private LayoutSet _layoutSet;
781            private LayoutType _layoutType;
782            private UnicodeProperties _typeSettingsProperties;
783    
784    }