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