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