1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    *
5    *
6    *
7    * The contents of this file are subject to the terms of the Liferay Enterprise
8    * Subscription License ("License"). You may not use this file except in
9    * compliance with the License. You can obtain a copy of the License by
10   * contacting Liferay, Inc. See the License for the specific language governing
11   * permissions and limitations under the License, including but not limited to
12   * distribution rights of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.model.impl;
24  
25  import com.liferay.portal.LayoutFriendlyURLException;
26  import com.liferay.portal.NoSuchGroupException;
27  import com.liferay.portal.PortalException;
28  import com.liferay.portal.SystemException;
29  import com.liferay.portal.kernel.log.Log;
30  import com.liferay.portal.kernel.log.LogFactoryUtil;
31  import com.liferay.portal.kernel.util.CharPool;
32  import com.liferay.portal.kernel.util.HttpUtil;
33  import com.liferay.portal.kernel.util.ListUtil;
34  import com.liferay.portal.kernel.util.LocaleUtil;
35  import com.liferay.portal.kernel.util.PropsKeys;
36  import com.liferay.portal.kernel.util.StringPool;
37  import com.liferay.portal.kernel.util.StringUtil;
38  import com.liferay.portal.kernel.util.UnicodeProperties;
39  import com.liferay.portal.kernel.util.Validator;
40  import com.liferay.portal.model.ColorScheme;
41  import com.liferay.portal.model.Group;
42  import com.liferay.portal.model.Layout;
43  import com.liferay.portal.model.LayoutConstants;
44  import com.liferay.portal.model.LayoutSet;
45  import com.liferay.portal.model.LayoutType;
46  import com.liferay.portal.model.LayoutTypePortlet;
47  import com.liferay.portal.model.Theme;
48  import com.liferay.portal.security.permission.ActionKeys;
49  import com.liferay.portal.security.permission.PermissionChecker;
50  import com.liferay.portal.service.GroupLocalServiceUtil;
51  import com.liferay.portal.service.LayoutLocalServiceUtil;
52  import com.liferay.portal.service.LayoutSetLocalServiceUtil;
53  import com.liferay.portal.service.ThemeLocalServiceUtil;
54  import com.liferay.portal.service.permission.LayoutPermissionUtil;
55  import com.liferay.portal.theme.ThemeDisplay;
56  import com.liferay.portal.util.CookieKeys;
57  import com.liferay.portal.util.LayoutClone;
58  import com.liferay.portal.util.LayoutCloneFactory;
59  import com.liferay.portal.util.PortalUtil;
60  import com.liferay.portal.util.PropsUtil;
61  import com.liferay.portal.util.PropsValues;
62  import com.liferay.portal.util.WebKeys;
63  import com.liferay.portlet.PortletURLImpl;
64  import com.liferay.util.LocalizationUtil;
65  
66  import java.io.IOException;
67  
68  import java.util.ArrayList;
69  import java.util.Iterator;
70  import java.util.List;
71  import java.util.Locale;
72  
73  import javax.portlet.PortletException;
74  import javax.portlet.PortletMode;
75  import javax.portlet.PortletRequest;
76  import javax.portlet.WindowState;
77  
78  import javax.servlet.http.HttpServletRequest;
79  
80  /**
81   * <a href="LayoutImpl.java.html"><b><i>View Source</i></b></a>
82   *
83   * @author Brian Wing Shun Chan
84   */
85  public class LayoutImpl extends LayoutModelImpl implements Layout {
86  
87      public static int validateFriendlyURL(String friendlyURL) {
88          if (friendlyURL.length() < 2) {
89              return LayoutFriendlyURLException.TOO_SHORT;
90          }
91  
92          if (!friendlyURL.startsWith(StringPool.SLASH)) {
93              return LayoutFriendlyURLException.DOES_NOT_START_WITH_SLASH;
94          }
95  
96          if (friendlyURL.endsWith(StringPool.SLASH)) {
97              return LayoutFriendlyURLException.ENDS_WITH_SLASH;
98          }
99  
100         if (friendlyURL.indexOf(StringPool.DOUBLE_SLASH) != -1) {
101             return LayoutFriendlyURLException.ADJACENT_SLASHES;
102         }
103 
104         for (char c : friendlyURL.toCharArray()) {
105             if ((!Validator.isChar(c)) && (!Validator.isDigit(c)) &&
106                 (c != CharPool.DASH) && (c != CharPool.PERCENT) &&
107                 (c != CharPool.PERIOD)  && (c != CharPool.PLUS) &&
108                 (c != CharPool.SLASH) && (c != CharPool.UNDERLINE)) {
109 
110                 return LayoutFriendlyURLException.INVALID_CHARACTERS;
111             }
112         }
113 
114         return -1;
115     }
116 
117     public static void validateFriendlyURLKeyword(String friendlyURL)
118         throws LayoutFriendlyURLException {
119 
120         String[] keywords = PropsUtil.getArray(
121             PropsKeys.LAYOUT_FRIENDLY_URL_KEYWORDS);
122 
123         for (int i = 0; i < keywords.length; i++) {
124             String keyword = keywords[i];
125 
126             if ((friendlyURL.indexOf(
127                     StringPool.SLASH + keyword + StringPool.SLASH) != -1) ||
128                 (friendlyURL.endsWith(StringPool.SLASH + keyword))) {
129 
130                 LayoutFriendlyURLException lfurle =
131                     new LayoutFriendlyURLException(
132                         LayoutFriendlyURLException.KEYWORD_CONFLICT);
133 
134                 lfurle.setKeywordConflict(keyword);
135 
136                 throw lfurle;
137             }
138         }
139     }
140 
141     public LayoutImpl() {
142     }
143 
144     public Group getGroup() {
145         Group group = null;
146 
147         try {
148             group = GroupLocalServiceUtil.getGroup(getGroupId());
149         }
150         catch (Exception e) {
151             group = new GroupImpl();
152 
153             _log.error(e, e);
154         }
155 
156         return group;
157     }
158 
159     public Group getScopeGroup() throws PortalException, SystemException {
160         Group group = null;
161 
162         try {
163             group = GroupLocalServiceUtil.getLayoutGroup(
164                 getCompanyId(), getPlid());
165         }
166         catch (NoSuchGroupException nsge) {
167         }
168 
169         return group;
170     }
171 
172     public boolean hasScopeGroup() throws PortalException, SystemException {
173         Group group = getScopeGroup();
174 
175         if (group != null) {
176             return true;
177         }
178         else {
179             return false;
180         }
181     }
182 
183     public boolean isPublicLayout() {
184         return !isPrivateLayout();
185     }
186 
187     public long getAncestorPlid() {
188         long plid = 0;
189 
190         try {
191             Layout layout = this;
192 
193             while (true) {
194                 if (!layout.isRootLayout()) {
195                     layout = LayoutLocalServiceUtil.getLayout(
196                         layout.getGroupId(), layout.isPrivateLayout(),
197                         layout.getParentLayoutId());
198                 }
199                 else {
200                     plid = layout.getPlid();
201 
202                     break;
203                 }
204             }
205         }
206         catch (Exception e) {
207             _log.error(e, e);
208         }
209 
210         return plid;
211     }
212 
213     public long getAncestorLayoutId() {
214         long layoutId = 0;
215 
216         try {
217             Layout layout = this;
218 
219             while (true) {
220                 if (!layout.isRootLayout()) {
221                     layout = LayoutLocalServiceUtil.getLayout(
222                         layout.getGroupId(), layout.isPrivateLayout(),
223                         layout.getParentLayoutId());
224                 }
225                 else {
226                     layoutId = layout.getLayoutId();
227 
228                     break;
229                 }
230             }
231         }
232         catch (Exception e) {
233             _log.error(e, e);
234         }
235 
236         return layoutId;
237     }
238 
239     public List<Layout> getAncestors() throws PortalException, SystemException {
240         List<Layout> layouts = new ArrayList<Layout>();
241 
242         Layout layout = this;
243 
244         while (true) {
245             if (!layout.isRootLayout()) {
246                 layout = LayoutLocalServiceUtil.getLayout(
247                     layout.getGroupId(), layout.isPrivateLayout(),
248                     layout.getParentLayoutId());
249 
250                 layouts.add(layout);
251             }
252             else {
253                 break;
254             }
255         }
256 
257         return layouts;
258     }
259 
260     public boolean hasAncestor(long layoutId)
261         throws PortalException, SystemException {
262 
263         long parentLayoutId = getParentLayoutId();
264 
265         while (isRootLayout()) {
266             if (parentLayoutId == layoutId) {
267                 return true;
268             }
269             else {
270                 Layout parentLayout = LayoutLocalServiceUtil.getLayout(
271                     getGroupId(), isPrivateLayout(), parentLayoutId);
272 
273                 parentLayoutId = parentLayout.getParentLayoutId();
274             }
275         }
276 
277         return false;
278     }
279 
280     public boolean isFirstParent() {
281         if (isFirstChild() && isRootLayout()) {
282             return true;
283         }
284         else {
285             return false;
286         }
287     }
288 
289     public boolean isFirstChild() {
290         if (getPriority() == 0) {
291             return true;
292         }
293         else {
294             return false;
295         }
296     }
297 
298     public boolean isRootLayout() {
299         if (getParentLayoutId() == LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
300             return true;
301         }
302         else {
303             return false;
304         }
305     }
306 
307     public List<Layout> getChildren() throws SystemException {
308         return LayoutLocalServiceUtil.getLayouts(
309             getGroupId(), isPrivateLayout(), getLayoutId());
310     }
311 
312     public List<Layout> getAllChildren() throws SystemException {
313         List<Layout> layouts = new ArrayList<Layout>();
314 
315         Iterator<Layout> itr = getChildren().iterator();
316 
317         while (itr.hasNext()) {
318             Layout layout = itr.next();
319 
320             layouts.add(layout);
321             layouts.addAll(layout.getChildren());
322         }
323 
324         return layouts;
325     }
326 
327     public List<Layout> getChildren(PermissionChecker permissionChecker)
328         throws PortalException, SystemException {
329 
330         List<Layout> layouts = ListUtil.copy(getChildren());
331 
332         Iterator<Layout> itr = layouts.iterator();
333 
334         while (itr.hasNext()) {
335             Layout layout = itr.next();
336 
337             if (layout.isHidden() ||
338                 !LayoutPermissionUtil.contains(
339                     permissionChecker, layout, ActionKeys.VIEW)) {
340 
341                 itr.remove();
342             }
343         }
344 
345         return layouts;
346     }
347 
348     public String getName(Locale locale) {
349         String localeLanguageId = LocaleUtil.toLanguageId(locale);
350 
351         return getName(localeLanguageId);
352     }
353 
354     public String getName(String localeLanguageId) {
355         return LocalizationUtil.getLocalization(getName(), localeLanguageId);
356     }
357 
358     public String getName(Locale locale, boolean useDefault) {
359         String localeLanguageId = LocaleUtil.toLanguageId(locale);
360 
361         return getName(localeLanguageId, useDefault);
362     }
363 
364     public String getName(String localeLanguageId, boolean useDefault) {
365         return LocalizationUtil.getLocalization(
366             getName(), localeLanguageId, useDefault);
367     }
368 
369     public void setName(String name, Locale locale) {
370         String localeLanguageId = LocaleUtil.toLanguageId(locale);
371 
372         if (Validator.isNotNull(name)) {
373             setName(
374                 LocalizationUtil.updateLocalization(
375                     getName(), "name", name, localeLanguageId));
376         }
377         else {
378             setName(
379                 LocalizationUtil.removeLocalization(
380                     getName(), "name", localeLanguageId));
381         }
382     }
383 
384     public String getTitle(Locale locale) {
385         String localeLanguageId = LocaleUtil.toLanguageId(locale);
386 
387         return getTitle(localeLanguageId);
388     }
389 
390     public String getTitle(String localeLanguageId) {
391         return LocalizationUtil.getLocalization(getTitle(), localeLanguageId);
392     }
393 
394     public String getTitle(Locale locale, boolean useDefault) {
395         String localeLanguageId = LocaleUtil.toLanguageId(locale);
396 
397         return getTitle(localeLanguageId, useDefault);
398     }
399 
400     public String getTitle(String localeLanguageId, boolean useDefault) {
401         return LocalizationUtil.getLocalization(
402             getTitle(), localeLanguageId, useDefault);
403     }
404 
405     public String getHTMLTitle(Locale locale) {
406         String localeLanguageId = LocaleUtil.toLanguageId(locale);
407 
408         return getHTMLTitle(localeLanguageId);
409     }
410 
411     public String getHTMLTitle(String localeLanguageId) {
412         String htmlTitle = getTitle(localeLanguageId);
413 
414         if (Validator.isNull(htmlTitle)) {
415             htmlTitle = getName(localeLanguageId);
416         }
417 
418         return htmlTitle;
419     }
420 
421     public void setTitle(String title, Locale locale) {
422         String localeLanguageId = LocaleUtil.toLanguageId(locale);
423 
424         if (Validator.isNotNull(title)) {
425             setTitle(
426                 LocalizationUtil.updateLocalization(
427                     getTitle(), "title", title, localeLanguageId));
428         }
429         else {
430             setTitle(
431                 LocalizationUtil.removeLocalization(
432                     getTitle(), "title", localeLanguageId));
433         }
434     }
435 
436     public LayoutType getLayoutType() {
437         return new LayoutTypePortletImpl(this);
438     }
439 
440     public String getTypeSettings() {
441         if (_typeSettingsProperties == null) {
442             return super.getTypeSettings();
443         }
444         else {
445             return _typeSettingsProperties.toString();
446         }
447     }
448 
449     public void setTypeSettings(String typeSettings) {
450         _typeSettingsProperties = null;
451 
452         super.setTypeSettings(typeSettings);
453     }
454 
455     public UnicodeProperties getTypeSettingsProperties() {
456         if (_typeSettingsProperties == null) {
457             _typeSettingsProperties = new UnicodeProperties(true);
458 
459             try {
460                 _typeSettingsProperties.load(super.getTypeSettings());
461             }
462             catch (IOException ioe) {
463                 _log.error(ioe, ioe);
464             }
465         }
466 
467         return _typeSettingsProperties;
468     }
469 
470     public void setTypeSettingsProperties(
471         UnicodeProperties typeSettingsProperties) {
472 
473         _typeSettingsProperties = typeSettingsProperties;
474 
475         super.setTypeSettings(_typeSettingsProperties.toString());
476     }
477 
478     public LayoutSet getLayoutSet() {
479         LayoutSet layoutSet = null;
480 
481         try {
482             layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
483                 getGroupId(), isPrivateLayout());
484         }
485         catch (Exception e) {
486             layoutSet = new LayoutSetImpl();
487 
488             _log.error(e, e);
489         }
490 
491         return layoutSet;
492     }
493 
494     public boolean isInheritLookAndFeel() {
495         if (Validator.isNull(getThemeId()) ||
496             Validator.isNull(getColorSchemeId())) {
497 
498             return true;
499         }
500         else {
501             return false;
502         }
503     }
504 
505     public Theme getTheme() throws SystemException {
506         if (isInheritLookAndFeel()) {
507             return getLayoutSet().getTheme();
508         }
509         else {
510             return ThemeLocalServiceUtil.getTheme(
511                 getCompanyId(), getThemeId(), false);
512         }
513     }
514 
515     public ColorScheme getColorScheme() throws SystemException {
516         if (isInheritLookAndFeel()) {
517             return getLayoutSet().getColorScheme();
518         }
519         else {
520             return ThemeLocalServiceUtil.getColorScheme(
521                 getCompanyId(), getTheme().getThemeId(), getColorSchemeId(),
522                 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 Theme getWapTheme() throws SystemException {
538         if (isInheritWapLookAndFeel()) {
539             return getLayoutSet().getWapTheme();
540         }
541         else {
542             return ThemeLocalServiceUtil.getTheme(
543                 getCompanyId(), getWapThemeId(), true);
544         }
545     }
546 
547     public ColorScheme getWapColorScheme() throws SystemException {
548         if (isInheritLookAndFeel()) {
549             return getLayoutSet().getWapColorScheme();
550         }
551         else {
552             return ThemeLocalServiceUtil.getColorScheme(
553                 getCompanyId(), getWapTheme().getThemeId(),
554                 getWapColorSchemeId(), true);
555         }
556     }
557 
558     public String getCssText() {
559         if (isInheritLookAndFeel()) {
560             return getLayoutSet().getCss();
561         }
562         else {
563             return getCss();
564         }
565     }
566 
567     public String getRegularURL(HttpServletRequest request)
568         throws SystemException {
569 
570         return _getURL(request, false, false);
571     }
572 
573     public String getResetMaxStateURL(HttpServletRequest request)
574         throws SystemException {
575 
576         return _getURL(request, true, false);
577     }
578 
579     public String getResetLayoutURL(HttpServletRequest request)
580         throws SystemException {
581 
582         return _getURL(request, true, true);
583     }
584 
585     public String getTarget() {
586         return PortalUtil.getLayoutTarget(this);
587     }
588 
589     public boolean isChildSelected(boolean selectable, Layout layout) {
590         if (selectable) {
591             long plid = getPlid();
592 
593             try {
594                 List<Layout> ancestors = layout.getAncestors();
595 
596                 for (Layout curLayout : ancestors) {
597                     if (plid == curLayout.getPlid()) {
598                         return true;
599                     }
600                 }
601             }
602             catch (Exception e) {
603                 _log.error(e, e);
604             }
605         }
606 
607         return false;
608     }
609 
610     public boolean isSelected(
611         boolean selectable, Layout layout, long ancestorPlid) {
612 
613         if (selectable) {
614             long plid = getPlid();
615 
616             if ((plid == layout.getPlid()) || (plid == ancestorPlid)) {
617                 return true;
618             }
619         }
620 
621         return false;
622     }
623 
624     private LayoutTypePortlet _getLayoutTypePortletClone(
625             HttpServletRequest request)
626         throws IOException {
627 
628         LayoutTypePortlet layoutTypePortlet = null;
629 
630         LayoutClone layoutClone = LayoutCloneFactory.getInstance();
631 
632         if (layoutClone != null) {
633             String typeSettings = layoutClone.get(request, getPlid());
634 
635             if (typeSettings != null) {
636                 UnicodeProperties props = new UnicodeProperties(true);
637 
638                 props.load(typeSettings);
639 
640                 String stateMax = props.getProperty(
641                     LayoutTypePortletImpl.STATE_MAX);
642                 String stateMin = props.getProperty(
643                     LayoutTypePortletImpl.STATE_MIN);
644 
645                 Layout layout = (Layout)this.clone();
646 
647                 layoutTypePortlet = (LayoutTypePortlet)layout.getLayoutType();
648 
649                 layoutTypePortlet.setStateMax(stateMax);
650                 layoutTypePortlet.setStateMin(stateMin);
651             }
652         }
653 
654         if (layoutTypePortlet == null) {
655             layoutTypePortlet = (LayoutTypePortlet)getLayoutType();
656         }
657 
658         return layoutTypePortlet;
659     }
660 
661     private String _getURL(
662             HttpServletRequest request, boolean resetMaxState,
663             boolean resetRenderParameters)
664         throws SystemException {
665 
666         ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
667             WebKeys.THEME_DISPLAY);
668 
669         if (resetMaxState) {
670             Layout layout = themeDisplay.getLayout();
671 
672             LayoutTypePortlet layoutTypePortlet = null;
673 
674             if (layout.equals(this)) {
675                 layoutTypePortlet = themeDisplay.getLayoutTypePortlet();
676             }
677             else {
678                 try {
679                     layoutTypePortlet = _getLayoutTypePortletClone(request);
680                 }
681                 catch (IOException ioe) {
682                     _log.error("Unable to clone layout settings", ioe);
683 
684                     layoutTypePortlet = (LayoutTypePortlet)getLayoutType();
685                 }
686             }
687 
688             if (layoutTypePortlet.hasStateMax()) {
689                 String portletId =
690                     StringUtil.split(layoutTypePortlet.getStateMax())[0];
691 
692                 PortletURLImpl portletURLImpl = new PortletURLImpl(
693                     request, portletId, getPlid(), PortletRequest.ACTION_PHASE);
694 
695                 try {
696                     portletURLImpl.setWindowState(WindowState.NORMAL);
697                     portletURLImpl.setPortletMode(PortletMode.VIEW);
698                 }
699                 catch (PortletException pe) {
700                     throw new SystemException(pe);
701                 }
702 
703                 portletURLImpl.setAnchor(false);
704 
705                 if (PropsValues.LAYOUT_DEFAULT_P_L_RESET &&
706                     !resetRenderParameters) {
707 
708                     portletURLImpl.setParameter("p_l_reset", "0");
709                 }
710                 else if (!PropsValues.LAYOUT_DEFAULT_P_L_RESET &&
711                          resetRenderParameters) {
712 
713                     portletURLImpl.setParameter("p_l_reset", "1");
714                 }
715 
716                 return portletURLImpl.toString();
717             }
718         }
719 
720         String url = PortalUtil.getLayoutURL(this, themeDisplay);
721 
722         if (!CookieKeys.hasSessionId(request)) {
723             url = PortalUtil.getURLWithSessionId(
724                 url, request.getSession().getId());
725         }
726 
727         if (!resetMaxState && !resetMaxState) {
728             return url;
729         }
730 
731         if (PropsValues.LAYOUT_DEFAULT_P_L_RESET && !resetRenderParameters) {
732             url = HttpUtil.addParameter(url, "p_l_reset", 0);
733         }
734         else if (!PropsValues.LAYOUT_DEFAULT_P_L_RESET &&
735                  resetRenderParameters) {
736 
737             url = HttpUtil.addParameter(url, "p_l_reset", 1);
738         }
739 
740         return url;
741     }
742 
743     private static Log _log = LogFactoryUtil.getLog(LayoutImpl.class);
744 
745     private UnicodeProperties _typeSettingsProperties = null;
746 
747 }