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