001    /**
002     * Copyright (c) 2000-present 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.kernel.configuration.Filter;
018    import com.liferay.portal.kernel.exception.PortalException;
019    import com.liferay.portal.kernel.exception.SystemException;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.portlet.PortletLayoutListener;
023    import com.liferay.portal.kernel.util.ArrayUtil;
024    import com.liferay.portal.kernel.util.DateFormatFactoryUtil;
025    import com.liferay.portal.kernel.util.FastDateFormatFactoryUtil;
026    import com.liferay.portal.kernel.util.GetterUtil;
027    import com.liferay.portal.kernel.util.ListUtil;
028    import com.liferay.portal.kernel.util.PropsKeys;
029    import com.liferay.portal.kernel.util.StringPool;
030    import com.liferay.portal.kernel.util.StringUtil;
031    import com.liferay.portal.kernel.util.UnicodeProperties;
032    import com.liferay.portal.kernel.util.Validator;
033    import com.liferay.portal.model.CustomizedPages;
034    import com.liferay.portal.model.Group;
035    import com.liferay.portal.model.Layout;
036    import com.liferay.portal.model.LayoutSet;
037    import com.liferay.portal.model.LayoutTemplate;
038    import com.liferay.portal.model.LayoutTypeController;
039    import com.liferay.portal.model.LayoutTypePortlet;
040    import com.liferay.portal.model.LayoutTypePortletConstants;
041    import com.liferay.portal.model.Plugin;
042    import com.liferay.portal.model.Portlet;
043    import com.liferay.portal.model.PortletConstants;
044    import com.liferay.portal.model.PortletPreferences;
045    import com.liferay.portal.model.PortletPreferencesIds;
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.security.permission.PermissionThreadLocal;
050    import com.liferay.portal.service.LayoutTemplateLocalServiceUtil;
051    import com.liferay.portal.service.PluginSettingLocalServiceUtil;
052    import com.liferay.portal.service.PortletLocalServiceUtil;
053    import com.liferay.portal.service.PortletPreferencesLocalServiceUtil;
054    import com.liferay.portal.service.permission.LayoutPermissionUtil;
055    import com.liferay.portal.service.permission.PortletPermissionUtil;
056    import com.liferay.portal.util.LayoutTypePortletFactoryUtil;
057    import com.liferay.portal.util.PortalUtil;
058    import com.liferay.portal.util.PortletKeys;
059    import com.liferay.portal.util.PropsUtil;
060    import com.liferay.portal.util.PropsValues;
061    import com.liferay.portlet.PortalPreferences;
062    import com.liferay.portlet.PortletPreferencesFactoryUtil;
063    import com.liferay.portlet.sites.util.SitesUtil;
064    import com.liferay.util.JS;
065    
066    import java.text.DateFormat;
067    import java.text.Format;
068    
069    import java.util.ArrayList;
070    import java.util.Date;
071    import java.util.HashSet;
072    import java.util.List;
073    import java.util.Map;
074    import java.util.Set;
075    
076    /**
077     * @author Brian Wing Shun Chan
078     * @author Berentey Zsolt
079     * @author Jorge Ferrer
080     * @author Raymond Aug??
081     */
082    public class LayoutTypePortletImpl
083            extends LayoutTypeImpl implements LayoutTypePortlet {
084    
085            public LayoutTypePortletImpl(
086                    Layout layout, LayoutTypeController layoutTypeController) {
087    
088                    super(layout, layoutTypeController);
089    
090                    if (_nestedPortletsNamespace == null) {
091                            _nestedPortletsNamespace = PortalUtil.getPortletNamespace(
092                                    PortletKeys.NESTED_PORTLETS);
093                    }
094    
095                    _layoutSetPrototypeLayout = SitesUtil.getLayoutSetPrototypeLayout(
096                            layout);
097            }
098    
099            @Override
100            public void addModeAboutPortletId(String portletId) {
101                    removeModesPortletId(portletId);
102                    setModeAbout(StringUtil.add(getModeAbout(), portletId));
103            }
104    
105            @Override
106            public void addModeConfigPortletId(String portletId) {
107                    removeModesPortletId(portletId);
108                    setModeConfig(StringUtil.add(getModeConfig(), portletId));
109            }
110    
111            @Override
112            public void addModeEditDefaultsPortletId(String portletId) {
113                    removeModesPortletId(portletId);
114                    setModeEditDefaults(StringUtil.add(getModeEditDefaults(), portletId));
115            }
116    
117            @Override
118            public void addModeEditGuestPortletId(String portletId) {
119                    removeModesPortletId(portletId);
120                    setModeEditGuest(StringUtil.add(getModeEditGuest(), portletId));
121            }
122    
123            @Override
124            public void addModeEditPortletId(String portletId) {
125                    removeModesPortletId(portletId);
126                    setModeEdit(StringUtil.add(getModeEdit(), portletId));
127            }
128    
129            @Override
130            public void addModeHelpPortletId(String portletId) {
131                    removeModesPortletId(portletId);
132                    setModeHelp(StringUtil.add(getModeHelp(), portletId));
133            }
134    
135            @Override
136            public void addModePreviewPortletId(String portletId) {
137                    removeModesPortletId(portletId);
138                    setModePreview(StringUtil.add(getModePreview(), portletId));
139            }
140    
141            @Override
142            public void addModePrintPortletId(String portletId) {
143                    removeModesPortletId(portletId);
144                    setModePrint(StringUtil.add(getModePrint(), portletId));
145            }
146    
147            @Override
148            public String addPortletId(long userId, String portletId)
149                    throws PortalException {
150    
151                    return addPortletId(userId, portletId, true);
152            }
153    
154            @Override
155            public String addPortletId(
156                            long userId, String portletId, boolean checkPermission)
157                    throws PortalException {
158    
159                    return addPortletId(userId, portletId, null, -1, checkPermission);
160            }
161    
162            @Override
163            public String addPortletId(
164                            long userId, String portletId, String columnId, int columnPos)
165                    throws PortalException {
166    
167                    return addPortletId(userId, portletId, columnId, columnPos, true);
168            }
169    
170            @Override
171            public String addPortletId(
172                            long userId, String portletId, String columnId, int columnPos,
173                            boolean checkPermission)
174                    throws PortalException {
175    
176                    return addPortletId(
177                            userId, portletId, columnId, columnPos, checkPermission, false);
178            }
179    
180            @Override
181            public void addPortletIds(
182                            long userId, String[] portletIds, boolean checkPermission)
183                    throws PortalException {
184    
185                    for (String portletId : portletIds) {
186                            addPortletId(userId, portletId, checkPermission);
187                    }
188            }
189    
190            @Override
191            public void addPortletIds(
192                            long userId, String[] portletIds, String columnId,
193                            boolean checkPermission)
194                    throws PortalException {
195    
196                    for (String portletId : portletIds) {
197                            addPortletId(userId, portletId, columnId, -1, checkPermission);
198                    }
199            }
200    
201            @Override
202            public void addStateMaxPortletId(String portletId) {
203                    removeStatesPortletId(portletId);
204                    //setStateMax(StringUtil.add(getStateMax(), portletId));
205                    setStateMax(StringUtil.add(StringPool.BLANK, portletId));
206            }
207    
208            @Override
209            public void addStateMinPortletId(String portletId) {
210                    removeStateMaxPortletId(portletId);
211                    setStateMin(StringUtil.add(getStateMin(), portletId));
212            }
213    
214            @Override
215            public List<Portlet> addStaticPortlets(
216                    List<Portlet> portlets, List<Portlet> startPortlets,
217                    List<Portlet> endPortlets) {
218    
219                    // Return the original array of portlets if no static portlets are
220                    // specified
221    
222                    if (startPortlets == null) {
223                            startPortlets = new ArrayList<Portlet>();
224                    }
225    
226                    if (endPortlets == null) {
227                            endPortlets = new ArrayList<Portlet>();
228                    }
229    
230                    if (startPortlets.isEmpty() && endPortlets.isEmpty()) {
231                            return portlets;
232                    }
233    
234                    // New array of portlets that contain the static portlets
235    
236                    List<Portlet> list = new ArrayList<Portlet>(
237                            portlets.size() + startPortlets.size() + endPortlets.size());
238    
239                    if (!startPortlets.isEmpty()) {
240                            list.addAll(startPortlets);
241                    }
242    
243                    for (int i = 0; i < portlets.size(); i++) {
244                            Portlet portlet = portlets.get(i);
245    
246                            // Add the portlet if and only if it is not also a static portlet
247    
248                            if (!startPortlets.contains(portlet) &&
249                                    !endPortlets.contains(portlet)) {
250    
251                                    list.add(portlet);
252                            }
253                    }
254    
255                    if (!endPortlets.isEmpty()) {
256                            list.addAll(endPortlets);
257                    }
258    
259                    return list;
260            }
261    
262            @Override
263            public List<Portlet> getAllPortlets() throws PortalException {
264                    List<Portlet> portlets = new ArrayList<Portlet>();
265    
266                    List<String> columns = getColumns();
267    
268                    for (int i = 0; i < columns.size(); i++) {
269                            String columnId = columns.get(i);
270    
271                            portlets.addAll(getAllPortlets(columnId));
272                    }
273    
274                    List<Portlet> staticPortlets = getStaticPortlets(
275                            PropsKeys.LAYOUT_STATIC_PORTLETS_ALL);
276    
277                    List<Portlet> embeddedPortlets = getEmbeddedPortlets(
278                            portlets, staticPortlets);
279    
280                    return addStaticPortlets(portlets, staticPortlets, embeddedPortlets);
281            }
282    
283            @Override
284            public List<Portlet> getAllPortlets(boolean includeSystem)
285                    throws PortalException {
286    
287                    List<Portlet> filteredPortlets = new ArrayList<Portlet>();
288    
289                    List<Portlet> portlets = getAllPortlets();
290    
291                    for (Portlet portlet : portlets) {
292                            if (portlet.isSystem() && !includeSystem) {
293                                    continue;
294                            }
295    
296                            filteredPortlets.add(portlet);
297                    }
298    
299                    return filteredPortlets;
300            }
301    
302            @Override
303            public List<Portlet> getAllPortlets(String columnId)
304                    throws PortalException {
305    
306                    String columnValue = getColumnValue(columnId);
307    
308                    String[] portletIds = StringUtil.split(columnValue);
309    
310                    List<Portlet> portlets = new ArrayList<Portlet>(portletIds.length);
311    
312                    for (String portletId : portletIds) {
313                            Portlet portlet = PortletLocalServiceUtil.getPortletById(
314                                    getCompanyId(), portletId);
315    
316                            if ((portlet != null) && !portlet.isUndeployedPortlet()) {
317                                    portlets.add(portlet);
318                            }
319                    }
320    
321                    List<Portlet> startPortlets = getStaticPortlets(
322                            PropsKeys.LAYOUT_STATIC_PORTLETS_START + columnId);
323    
324                    List<Portlet> endPortlets = getStaticPortlets(
325                            PropsKeys.LAYOUT_STATIC_PORTLETS_END + columnId);
326    
327                    return addStaticPortlets(portlets, startPortlets, endPortlets);
328            }
329    
330            @Override
331            public Layout getLayoutSetPrototypeLayout() {
332                    return _layoutSetPrototypeLayout;
333            }
334    
335            @Override
336            public String getLayoutSetPrototypeLayoutProperty(String key) {
337                    if (_layoutSetPrototypeLayout == null) {
338                            return StringPool.BLANK;
339                    }
340    
341                    UnicodeProperties typeSettingsProperties =
342                            _layoutSetPrototypeLayout.getTypeSettingsProperties();
343    
344                    return typeSettingsProperties.getProperty(key);
345            }
346    
347            @Override
348            public LayoutTemplate getLayoutTemplate() {
349                    String themeId = getThemeId();
350    
351                    LayoutTemplate layoutTemplate =
352                            LayoutTemplateLocalServiceUtil.getLayoutTemplate(
353                                    getLayoutTemplateId(), false, themeId);
354    
355                    if (layoutTemplate == null) {
356                            layoutTemplate = new LayoutTemplateImpl(
357                                    StringPool.BLANK, StringPool.BLANK);
358    
359                            List<String> columns = new ArrayList<String>();
360    
361                            for (int i = 1; i <= 10; i++) {
362                                    columns.add(LayoutTypePortletConstants.COLUMN_PREFIX + i);
363                            }
364    
365                            layoutTemplate.setColumns(columns);
366                    }
367    
368                    return layoutTemplate;
369            }
370    
371            @Override
372            public String getLayoutTemplateId() {
373                    return GetterUtil.getString(
374                            getTypeSettingsProperty(
375                                    LayoutTypePortletConstants.LAYOUT_TEMPLATE_ID));
376            }
377    
378            @Override
379            public String getModeAbout() {
380                    return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_ABOUT);
381            }
382    
383            @Override
384            public String getModeConfig() {
385                    return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_CONFIG);
386            }
387    
388            @Override
389            public String getModeEdit() {
390                    return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_EDIT);
391            }
392    
393            @Override
394            public String getModeEditDefaults() {
395                    return getTypeSettingsProperty(
396                            LayoutTypePortletConstants.MODE_EDIT_DEFAULTS);
397            }
398    
399            @Override
400            public String getModeEditGuest() {
401                    return getTypeSettingsProperty(
402                            LayoutTypePortletConstants.MODE_EDIT_GUEST);
403            }
404    
405            @Override
406            public String getModeHelp() {
407                    return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_HELP);
408            }
409    
410            @Override
411            public String getModePreview() {
412                    return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_PREVIEW);
413            }
414    
415            @Override
416            public String getModePrint() {
417                    return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_PRINT);
418            }
419    
420            @Override
421            public int getNumOfColumns() {
422                    return getLayoutTemplate().getColumns().size();
423            }
424    
425            @Override
426            public PortalPreferences getPortalPreferences() {
427                    return _portalPreferences;
428            }
429    
430            @Override
431            public List<String> getPortletIds() {
432                    List<String> portletIds = new ArrayList<String>();
433    
434                    List<String> columns = getColumns();
435    
436                    for (int i = 0; i < columns.size(); i++) {
437                            String columnId = columns.get(i);
438    
439                            String columnValue = getColumnValue(columnId);
440    
441                            portletIds.addAll(
442                                    ListUtil.fromArray(StringUtil.split(columnValue)));
443                    }
444    
445                    return portletIds;
446            }
447    
448            @Override
449            public List<Portlet> getPortlets() {
450                    List<String> portletIds = getPortletIds();
451    
452                    List<Portlet> portlets = new ArrayList<Portlet>(portletIds.size());
453    
454                    for (int i = 0; i < portletIds.size(); i++) {
455                            String portletId = portletIds.get(i);
456    
457                            Portlet portlet = PortletLocalServiceUtil.getPortletById(
458                                    getCompanyId(), portletId);
459    
460                            if (portlet != null) {
461                                    portlets.add(portlet);
462                            }
463                    }
464    
465                    return portlets;
466            }
467    
468            @Override
469            public String getStateMax() {
470                    return getTypeSettingsProperty(LayoutTypePortletConstants.STATE_MAX);
471            }
472    
473            @Override
474            public String getStateMaxPortletId() {
475                    String[] stateMax = StringUtil.split(getStateMax());
476    
477                    if (stateMax.length > 0) {
478                            return stateMax[0];
479                    }
480                    else {
481                            return StringPool.BLANK;
482                    }
483            }
484    
485            @Override
486            public String getStateMin() {
487                    return getTypeSettingsProperty(LayoutTypePortletConstants.STATE_MIN);
488            }
489    
490            @Override
491            public boolean hasDefaultScopePortletId(long groupId, String portletId)
492                    throws PortalException {
493    
494                    if (hasPortletId(portletId)) {
495                            long scopeGroupId = PortalUtil.getScopeGroupId(
496                                    getLayout(), portletId);
497    
498                            if (groupId == scopeGroupId) {
499                                    return true;
500                            }
501                    }
502    
503                    return false;
504            }
505    
506            @Override
507            public boolean hasModeAboutPortletId(String portletId) {
508                    return StringUtil.contains(getModeAbout(), portletId);
509            }
510    
511            @Override
512            public boolean hasModeConfigPortletId(String portletId) {
513                    return StringUtil.contains(getModeConfig(), portletId);
514            }
515    
516            @Override
517            public boolean hasModeEditDefaultsPortletId(String portletId) {
518                    return StringUtil.contains(getModeEditDefaults(), portletId);
519            }
520    
521            @Override
522            public boolean hasModeEditGuestPortletId(String portletId) {
523                    return StringUtil.contains(getModeEditGuest(), portletId);
524            }
525    
526            @Override
527            public boolean hasModeEditPortletId(String portletId) {
528                    return StringUtil.contains(getModeEdit(), portletId);
529            }
530    
531            @Override
532            public boolean hasModeHelpPortletId(String portletId) {
533                    return StringUtil.contains(getModeHelp(), portletId);
534            }
535    
536            @Override
537            public boolean hasModePreviewPortletId(String portletId) {
538                    return StringUtil.contains(getModePreview(), portletId);
539            }
540    
541            @Override
542            public boolean hasModePrintPortletId(String portletId) {
543                    return StringUtil.contains(getModePrint(), portletId);
544            }
545    
546            @Override
547            public boolean hasModeViewPortletId(String portletId) {
548                    if (hasModeAboutPortletId(portletId) ||
549                            hasModeConfigPortletId(portletId) ||
550                            hasModeEditPortletId(portletId) ||
551                            hasModeEditDefaultsPortletId(portletId) ||
552                            hasModeEditGuestPortletId(portletId) ||
553                            hasModeHelpPortletId(portletId) ||
554                            hasModePreviewPortletId(portletId) ||
555                            hasModePrintPortletId(portletId)) {
556    
557                            return false;
558                    }
559                    else {
560                            return true;
561                    }
562            }
563    
564            @Override
565            public boolean hasPortletId(String portletId) throws PortalException {
566                    return hasPortletId(portletId, false);
567            }
568    
569            @Override
570            public boolean hasPortletId(String portletId, boolean strict)
571                    throws PortalException {
572    
573                    List<String> columns = getColumns();
574    
575                    for (String columnId : columns) {
576                            if (hasNonstaticPortletId(columnId, portletId)) {
577                                    return true;
578                            }
579    
580                            if (hasStaticPortletId(columnId, portletId)) {
581                                    return true;
582                            }
583                    }
584    
585                    Layout layout = getLayout();
586    
587                    if (layout.isTypeControlPanel()) {
588                            return false;
589                    }
590    
591                    if (isCustomizable() && isCustomizedView()) {
592                            LayoutTypePortletImpl defaultLayoutTypePortletImpl =
593                                    getDefaultLayoutTypePortletImpl();
594    
595                            if (defaultLayoutTypePortletImpl.hasNonstaticPortletId(portletId)) {
596                                    return false;
597                            }
598                    }
599    
600                    if (!strict &&
601                            ((PortletPreferencesLocalServiceUtil.getPortletPreferencesCount(
602                                    PortletKeys.PREFS_OWNER_TYPE_LAYOUT, layout.getPlid(),
603                                    portletId) > 0) ||
604                             (PortletPreferencesLocalServiceUtil.getPortletPreferencesCount(
605                                    PortletKeys.PREFS_OWNER_TYPE_USER, layout.getPlid(),
606                                    portletId) > 0))) {
607    
608                            return true;
609                    }
610    
611                    return false;
612            }
613    
614            @Override
615            public boolean hasStateMax() {
616                    String[] stateMax = StringUtil.split(getStateMax());
617    
618                    if (stateMax.length > 0) {
619                            return true;
620                    }
621                    else {
622                            return false;
623                    }
624            }
625    
626            @Override
627            public boolean hasStateMaxPortletId(String portletId) {
628                    if (StringUtil.contains(getStateMax(), portletId)) {
629                            return true;
630                    }
631                    else {
632                            return false;
633                    }
634            }
635    
636            @Override
637            public boolean hasStateMin() {
638                    String[] stateMin = StringUtil.split(getStateMin());
639    
640                    if (stateMin.length > 0) {
641                            return true;
642                    }
643                    else {
644                            return false;
645                    }
646            }
647    
648            @Override
649            public boolean hasStateMinPortletId(String portletId) {
650                    if (StringUtil.contains(getStateMin(), portletId)) {
651                            return true;
652                    }
653                    else {
654                            return false;
655                    }
656            }
657    
658            @Override
659            public boolean hasStateNormalPortletId(String portletId) {
660                    if (hasStateMaxPortletId(portletId) ||
661                            hasStateMinPortletId(portletId)) {
662    
663                            return false;
664                    }
665                    else {
666                            return true;
667                    }
668            }
669    
670            @Override
671            public boolean hasUpdatePermission() {
672                    return _updatePermission;
673            }
674    
675            @Override
676            public boolean isCacheable() throws PortalException {
677                    for (String columnId : getColumns()) {
678                            for (Portlet portlet : getAllPortlets(columnId)) {
679                                    Portlet rootPortlet = portlet.getRootPortlet();
680    
681                                    if (!rootPortlet.isLayoutCacheable()) {
682                                            return false;
683                                    }
684                            }
685                    }
686    
687                    return true;
688            }
689    
690            @Override
691            public boolean isColumnCustomizable(String columnId) {
692                    if (!isLayoutSetPrototype()) {
693                            String customizableString = getTypeSettingsProperty(
694                                    CustomizedPages.namespaceColumnId(columnId));
695    
696                            boolean customizable = GetterUtil.getBoolean(customizableString);
697    
698                            if (!customizable && hasUserPreferences()) {
699                                    String columnValue = _portalPreferences.getValue(
700                                            CustomizedPages.namespacePlid(getPlid()), columnId,
701                                            StringPool.NULL);
702    
703                                    if (!Validator.equals(columnValue, StringPool.NULL)) {
704                                            setUserPreference(columnId, null);
705                                    }
706                            }
707    
708                            return customizable;
709                    }
710    
711                    return false;
712            }
713    
714            @Override
715            public boolean isColumnDisabled(String columnId) {
716                    if ((isCustomizedView() && !isColumnCustomizable(columnId)) ||
717                            (!isCustomizedView() && !hasUpdatePermission())) {
718    
719                            return true;
720                    }
721    
722                    return false;
723            }
724    
725            @Override
726            public boolean isCustomizable() {
727                    for (String columnId : getColumns()) {
728                            if (isColumnCustomizable(columnId)) {
729                                    return true;
730                            }
731                    }
732    
733                    return false;
734            }
735    
736            @Override
737            public boolean isCustomizedView() {
738                    return _customizedView;
739            }
740    
741            @Override
742            public boolean isDefaultUpdated() {
743                    if (!isCustomizedView() || !hasUserPreferences()) {
744                            return false;
745                    }
746    
747                    String preferencesModifiedDateString = _portalPreferences.getValue(
748                            CustomizedPages.namespacePlid(getPlid()), _MODIFIED_DATE,
749                            _NULL_DATE);
750    
751                    DateFormat dateFormat = DateFormatFactoryUtil.getSimpleDateFormat(
752                            PropsValues.INDEX_DATE_FORMAT_PATTERN);
753    
754                    try {
755                            Date preferencesModifiedDate = dateFormat.parse(
756                                    preferencesModifiedDateString);
757    
758                            Layout layout = getLayout();
759    
760                            String propertiesModifiedDateString =
761                                    layout.getTypeSettingsProperty(_MODIFIED_DATE, _NULL_DATE);
762    
763                            Date propertiesModifiedDate = dateFormat.parse(
764                                    propertiesModifiedDateString);
765    
766                            return propertiesModifiedDate.after(preferencesModifiedDate);
767                    }
768                    catch (Exception e) {
769                            _log.error(e, e);
770                    }
771    
772                    return false;
773            }
774    
775            @Override
776            public boolean isPortletCustomizable(String portletId) {
777                    return isColumnCustomizable(getColumn(portletId));
778            }
779    
780            @Override
781            public void movePortletId(
782                            long userId, String portletId, String columnId, int columnPos)
783                    throws PortalException {
784    
785                    if (!hasPortletId(portletId)) {
786                            return;
787                    }
788    
789                    _enablePortletLayoutListener = false;
790    
791                    try {
792                            removePortletId(userId, portletId, false);
793                            addPortletId(userId, portletId, columnId, columnPos, false, true);
794                    }
795                    finally {
796                            _enablePortletLayoutListener = true;
797                    }
798    
799                    Layout layout = getLayout();
800    
801                    try {
802                            Portlet portlet = PortletLocalServiceUtil.getPortletById(
803                                    layout.getCompanyId(), portletId);
804    
805                            if (portlet != null) {
806                                    PortletLayoutListener portletLayoutListener =
807                                            portlet.getPortletLayoutListenerInstance();
808    
809                                    if (portletLayoutListener != null) {
810                                            portletLayoutListener.onMoveInLayout(
811                                                    portletId, layout.getPlid());
812                                    }
813                            }
814                    }
815                    catch (Exception e) {
816                            _log.error("Unable to fire portlet layout listener event", e);
817                    }
818            }
819    
820            @Override
821            public void removeModeAboutPortletId(String portletId) {
822                    setModeAbout(StringUtil.removeFromList(getModeAbout(), portletId));
823            }
824    
825            @Override
826            public void removeModeConfigPortletId(String portletId) {
827                    setModeConfig(StringUtil.removeFromList(getModeConfig(), portletId));
828            }
829    
830            @Override
831            public void removeModeEditDefaultsPortletId(String portletId) {
832                    setModeEditDefaults(
833                            StringUtil.removeFromList(getModeEditDefaults(), portletId));
834            }
835    
836            @Override
837            public void removeModeEditGuestPortletId(String portletId) {
838                    setModeEditGuest(
839                            StringUtil.removeFromList(getModeEditGuest(), portletId));
840            }
841    
842            @Override
843            public void removeModeEditPortletId(String portletId) {
844                    setModeEdit(StringUtil.removeFromList(getModeEdit(), portletId));
845            }
846    
847            @Override
848            public void removeModeHelpPortletId(String portletId) {
849                    setModeHelp(StringUtil.removeFromList(getModeHelp(), portletId));
850            }
851    
852            @Override
853            public void removeModePreviewPortletId(String portletId) {
854                    setModePreview(StringUtil.removeFromList(getModePreview(), portletId));
855            }
856    
857            @Override
858            public void removeModePrintPortletId(String portletId) {
859                    setModePrint(StringUtil.removeFromList(getModePrint(), portletId));
860            }
861    
862            @Override
863            public void removeModesPortletId(String portletId) {
864                    removeModeAboutPortletId(portletId);
865                    removeModeConfigPortletId(portletId);
866                    removeModeEditPortletId(portletId);
867                    removeModeEditDefaultsPortletId(portletId);
868                    removeModeEditGuestPortletId(portletId);
869                    removeModeHelpPortletId(portletId);
870                    removeModePreviewPortletId(portletId);
871                    removeModePrintPortletId(portletId);
872            }
873    
874            @Override
875            public void removeNestedColumns(String portletNamespace) {
876                    UnicodeProperties typeSettingsProperties = getTypeSettingsProperties();
877    
878                    UnicodeProperties newTypeSettingsProperties = new UnicodeProperties();
879    
880                    for (Map.Entry<String, String> entry :
881                                    typeSettingsProperties.entrySet()) {
882    
883                            String key = entry.getKey();
884    
885                            if (!key.startsWith(portletNamespace)) {
886                                    newTypeSettingsProperties.setProperty(key, entry.getValue());
887                            }
888                    }
889    
890                    Layout layout = getLayout();
891    
892                    layout.setTypeSettingsProperties(newTypeSettingsProperties);
893    
894                    String nestedColumnIds = GetterUtil.getString(
895                            getTypeSettingsProperty(
896                                    LayoutTypePortletConstants.NESTED_COLUMN_IDS));
897    
898                    String[] nestedColumnIdsArray = ArrayUtil.removeByPrefix(
899                            StringUtil.split(nestedColumnIds), portletNamespace);
900    
901                    setTypeSettingsProperty(
902                            LayoutTypePortletConstants.NESTED_COLUMN_IDS,
903                            StringUtil.merge(nestedColumnIdsArray));
904            }
905    
906            @Override
907            public void removePortletId(long userId, String portletId) {
908                    removePortletId(userId, portletId, true);
909            }
910    
911            @Override
912            public void removePortletId(
913                    long userId, String portletId, boolean cleanUp) {
914    
915                    try {
916                            Portlet portlet = PortletLocalServiceUtil.getPortletById(
917                                    getCompanyId(), portletId);
918    
919                            if (portlet == null) {
920                                    _log.error(
921                                            "Portlet " + portletId +
922                                                    " cannot be removed because it is not registered");
923    
924                                    return;
925                            }
926    
927                            PermissionChecker permissionChecker =
928                                    PermissionThreadLocal.getPermissionChecker();
929    
930                            if (!LayoutPermissionUtil.contains(
931                                            permissionChecker, getLayout(), ActionKeys.UPDATE) &&
932                                    !isCustomizable()) {
933    
934                                    return;
935                            }
936                    }
937                    catch (Exception e) {
938                            _log.error(e, e);
939    
940                            return;
941                    }
942    
943                    List<String> columns = getColumns();
944    
945                    for (int i = 0; i < columns.size(); i++) {
946                            String columnId = columns.get(i);
947    
948                            if (isCustomizable() && isColumnDisabled(columnId)) {
949                                    continue;
950                            }
951    
952                            String columnValue = StringPool.BLANK;
953    
954                            if (hasUserPreferences()) {
955                                    columnValue = getUserPreference(columnId);
956                            }
957                            else {
958                                    columnValue = getTypeSettingsProperty(columnId);
959                            }
960    
961                            columnValue = StringUtil.removeFromList(columnValue, portletId);
962    
963                            if (hasUserPreferences()) {
964                                    setUserPreference(columnId, columnValue);
965                            }
966                            else {
967                                    setTypeSettingsProperty(columnId, columnValue);
968                            }
969                    }
970    
971                    if (cleanUp) {
972                            try {
973                                    onRemoveFromLayout(new String[] {portletId});
974                            }
975                            catch (Exception e) {
976                                    _log.error(e, e);
977                            }
978                    }
979            }
980    
981            @Override
982            public void removeStateMaxPortletId(String portletId) {
983                    setStateMax(StringUtil.removeFromList(getStateMax(), portletId));
984            }
985    
986            @Override
987            public void removeStateMinPortletId(String portletId) {
988                    setStateMin(StringUtil.removeFromList(getStateMin(), portletId));
989            }
990    
991            @Override
992            public void removeStatesPortletId(String portletId) {
993                    removeStateMaxPortletId(portletId);
994                    removeStateMinPortletId(portletId);
995            }
996    
997            @Override
998            public void reorganizePortlets(
999                    List<String> newColumns, List<String> oldColumns) {
1000    
1001                    String lastNewColumnId = newColumns.get(newColumns.size() - 1);
1002                    String lastNewColumnValue = getTypeSettingsProperty(lastNewColumnId);
1003    
1004                    for (String oldColumnId : oldColumns) {
1005                            if (!newColumns.contains(oldColumnId)) {
1006                                    String oldColumnValue = getTypeSettingsProperties().remove(
1007                                            oldColumnId);
1008    
1009                                    String[] portletIds = StringUtil.split(oldColumnValue);
1010    
1011                                    for (String portletId : portletIds) {
1012                                            lastNewColumnValue = StringUtil.add(
1013                                                    lastNewColumnValue, portletId);
1014                                    }
1015                            }
1016                    }
1017    
1018                    setTypeSettingsProperty(lastNewColumnId, lastNewColumnValue);
1019            }
1020    
1021            @Override
1022            public void resetModes() {
1023                    setModeAbout(StringPool.BLANK);
1024                    setModeConfig(StringPool.BLANK);
1025                    setModeEdit(StringPool.BLANK);
1026                    setModeEditDefaults(StringPool.BLANK);
1027                    setModeEditGuest(StringPool.BLANK);
1028                    setModeHelp(StringPool.BLANK);
1029                    setModePreview(StringPool.BLANK);
1030                    setModePrint(StringPool.BLANK);
1031            }
1032    
1033            @Override
1034            public void resetStates() {
1035                    setStateMax(StringPool.BLANK);
1036                    setStateMin(StringPool.BLANK);
1037            }
1038    
1039            @Override
1040            public void resetUserPreferences() {
1041                    if (!hasUserPreferences()) {
1042                            return;
1043                    }
1044    
1045                    long plid = getPlid();
1046    
1047                    Set<String> customPortletIds = new HashSet<String>();
1048    
1049                    for (String columnId : getColumns()) {
1050                            String value = _portalPreferences.getValue(
1051                                    CustomizedPages.namespacePlid(plid), columnId);
1052    
1053                            for (String customPortletId : StringUtil.split(value)) {
1054                                    customPortletIds.add(customPortletId);
1055                            }
1056                    }
1057    
1058                    try {
1059                            onRemoveFromLayout(
1060                                    customPortletIds.toArray(new String[customPortletIds.size()]));
1061                    }
1062                    catch (Exception e) {
1063                            _log.error(e, e);
1064                    }
1065    
1066                    _portalPreferences.resetValues(CustomizedPages.namespacePlid(plid));
1067    
1068                    _portalPreferences.setValue(
1069                            CustomizedPages.namespacePlid(plid), _MODIFIED_DATE,
1070                            _dateFormat.format(new Date()));
1071            }
1072    
1073            @Override
1074            public void setCustomizedView(boolean customizedView) {
1075                    _customizedView = customizedView;
1076            }
1077    
1078            @Override
1079            public void setLayoutTemplateId(long userId, String newLayoutTemplateId) {
1080                    setLayoutTemplateId(userId, newLayoutTemplateId, true);
1081            }
1082    
1083            @Override
1084            public void setLayoutTemplateId(
1085                    long userId, String newLayoutTemplateId, boolean checkPermission) {
1086    
1087                    if (checkPermission &&
1088                            !PluginSettingLocalServiceUtil.hasPermission(
1089                                    userId, newLayoutTemplateId, Plugin.TYPE_LAYOUT_TEMPLATE)) {
1090    
1091                            return;
1092                    }
1093    
1094                    LayoutTemplate oldLayoutTemplate = getLayoutTemplate();
1095    
1096                    String themeId = getThemeId();
1097    
1098                    LayoutTemplate newLayoutTemplate =
1099                            LayoutTemplateLocalServiceUtil.getLayoutTemplate(
1100                                    newLayoutTemplateId, false, themeId);
1101    
1102                    if (newLayoutTemplate == null) {
1103                            if (_log.isWarnEnabled()) {
1104                                    _log.warn(
1105                                            "Unable to find layout template " + newLayoutTemplateId);
1106                            }
1107    
1108                            return;
1109                    }
1110    
1111                    setTypeSettingsProperty(
1112                            LayoutTypePortletConstants.LAYOUT_TEMPLATE_ID, newLayoutTemplateId);
1113    
1114                    List<String> oldColumns = oldLayoutTemplate.getColumns();
1115                    List<String> newColumns = newLayoutTemplate.getColumns();
1116    
1117                    reorganizePortlets(newColumns, oldColumns);
1118            }
1119    
1120            @Override
1121            public void setModeAbout(String modeAbout) {
1122                    setTypeSettingsProperty(
1123                            LayoutTypePortletConstants.MODE_ABOUT, modeAbout);
1124            }
1125    
1126            @Override
1127            public void setModeConfig(String modeConfig) {
1128                    setTypeSettingsProperty(
1129                            LayoutTypePortletConstants.MODE_CONFIG, modeConfig);
1130            }
1131    
1132            @Override
1133            public void setModeEdit(String modeEdit) {
1134                    setTypeSettingsProperty(LayoutTypePortletConstants.MODE_EDIT, modeEdit);
1135            }
1136    
1137            @Override
1138            public void setModeEditDefaults(String modeEditDefaults) {
1139                    setTypeSettingsProperty(
1140                            LayoutTypePortletConstants.MODE_EDIT_DEFAULTS, modeEditDefaults);
1141            }
1142    
1143            @Override
1144            public void setModeEditGuest(String modeEditGuest) {
1145                    setTypeSettingsProperty(
1146                            LayoutTypePortletConstants.MODE_EDIT_GUEST, modeEditGuest);
1147            }
1148    
1149            @Override
1150            public void setModeHelp(String modeHelp) {
1151                    setTypeSettingsProperty(LayoutTypePortletConstants.MODE_HELP, modeHelp);
1152            }
1153    
1154            @Override
1155            public void setModePreview(String modePreview) {
1156                    setTypeSettingsProperty(
1157                            LayoutTypePortletConstants.MODE_PREVIEW, modePreview);
1158            }
1159    
1160            @Override
1161            public void setModePrint(String modePrint) {
1162                    setTypeSettingsProperty(
1163                            LayoutTypePortletConstants.MODE_PRINT, modePrint);
1164            }
1165    
1166            @Override
1167            public void setPortalPreferences(PortalPreferences portalPreferences) {
1168                    _portalPreferences = portalPreferences;
1169            }
1170    
1171            @Override
1172            public void setStateMax(String stateMax) {
1173                    setTypeSettingsProperty(LayoutTypePortletConstants.STATE_MAX, stateMax);
1174            }
1175    
1176            @Override
1177            public void setStateMin(String stateMin) {
1178                    setTypeSettingsProperty(LayoutTypePortletConstants.STATE_MIN, stateMin);
1179            }
1180    
1181            @Override
1182            public void setUpdatePermission(boolean updatePermission) {
1183                    _updatePermission = updatePermission;
1184            }
1185    
1186            protected void addNestedColumn(String columnId) {
1187                    String nestedColumnIds = getTypeSettingsProperty(
1188                            LayoutTypePortletConstants.NESTED_COLUMN_IDS, StringPool.BLANK);
1189    
1190                    if (!nestedColumnIds.contains(columnId)) {
1191                            nestedColumnIds = StringUtil.add(nestedColumnIds, columnId);
1192    
1193                            setTypeSettingsProperty(
1194                                    LayoutTypePortletConstants.NESTED_COLUMN_IDS, nestedColumnIds);
1195                    }
1196            }
1197    
1198            protected String addPortletId(
1199                            long userId, String portletId, String columnId, int columnPos,
1200                            boolean checkPermission, boolean strictHasPortlet)
1201                    throws PortalException {
1202    
1203                    portletId = JS.getSafeName(portletId);
1204    
1205                    Layout layout = getLayout();
1206    
1207                    Portlet portlet = null;
1208    
1209                    try {
1210                            portlet = PortletLocalServiceUtil.getPortletById(
1211                                    layout.getCompanyId(), portletId);
1212    
1213                            if (portlet == null) {
1214                                    if (_log.isWarnEnabled()) {
1215                                            _log.warn(
1216                                                    "Portlet " + portletId +
1217                                                            " cannot be added because it is not registered");
1218                                    }
1219    
1220                                    return null;
1221                            }
1222    
1223                            PermissionChecker permissionChecker =
1224                                    PermissionThreadLocal.getPermissionChecker();
1225    
1226                            if (checkPermission &&
1227                                    !PortletPermissionUtil.contains(
1228                                            permissionChecker, layout, portlet,
1229                                            ActionKeys.ADD_TO_PAGE)) {
1230    
1231                                    return null;
1232                            }
1233                    }
1234                    catch (Exception e) {
1235                            _log.error(e, e);
1236                    }
1237    
1238                    if (portlet.isSystem()) {
1239                            return null;
1240                    }
1241    
1242                    if (portlet.isInstanceable() &&
1243                            !PortletConstants.hasInstanceId(portletId)) {
1244    
1245                            portletId = PortletConstants.assemblePortletId(
1246                                    portletId, PortletConstants.generateInstanceId());
1247                    }
1248    
1249                    if (hasPortletId(portletId, strictHasPortlet)) {
1250                            return null;
1251                    }
1252    
1253                    if (columnId == null) {
1254                            LayoutTemplate layoutTemplate = getLayoutTemplate();
1255    
1256                            List<String> columns = layoutTemplate.getColumns();
1257    
1258                            if (!columns.isEmpty()) {
1259                                    columnId = columns.get(0);
1260                            }
1261                    }
1262    
1263                    if (columnId == null) {
1264                            return null;
1265                    }
1266    
1267                    if (isCustomizable()) {
1268                            if (isColumnDisabled(columnId)) {
1269                                    return null;
1270                            }
1271    
1272                            if ((PortletConstants.hasInstanceId(portletId) ||
1273                                     portlet.isPreferencesUniquePerLayout()) &&
1274                                    hasUserPreferences()) {
1275    
1276                                    portletId = PortletConstants.assemblePortletId(
1277                                            portletId, userId);
1278                            }
1279                    }
1280    
1281                    String columnValue = StringPool.BLANK;
1282    
1283                    if (hasUserPreferences()) {
1284                            columnValue = getUserPreference(columnId);
1285                    }
1286                    else {
1287                            columnValue = getTypeSettingsProperty(columnId);
1288                    }
1289    
1290                    if ((columnValue == null) &&
1291                            columnId.startsWith(_nestedPortletsNamespace)) {
1292    
1293                            addNestedColumn(columnId);
1294                    }
1295    
1296                    if (columnPos >= 0) {
1297                            List<String> portletIds = ListUtil.fromArray(
1298                                    StringUtil.split(columnValue));
1299    
1300                            if (columnPos <= portletIds.size()) {
1301                                    portletIds.add(columnPos, portletId);
1302                            }
1303                            else {
1304                                    portletIds.add(portletId);
1305                            }
1306    
1307                            columnValue = StringUtil.merge(portletIds);
1308                    }
1309                    else {
1310                            columnValue = StringUtil.add(columnValue, portletId);
1311                    }
1312    
1313                    if (hasUserPreferences()) {
1314                            setUserPreference(columnId, columnValue);
1315                    }
1316                    else {
1317                            setTypeSettingsProperty(columnId, columnValue);
1318                    }
1319    
1320                    try {
1321                            if (_enablePortletLayoutListener) {
1322                                    PortletLayoutListener portletLayoutListener =
1323                                            portlet.getPortletLayoutListenerInstance();
1324    
1325                                    if (portletLayoutListener != null) {
1326                                            portletLayoutListener.onAddToLayout(
1327                                                    portletId, layout.getPlid());
1328                                    }
1329                            }
1330                    }
1331                    catch (Exception e) {
1332                            _log.error("Unable to fire portlet layout listener event", e);
1333                    }
1334    
1335                    return portletId;
1336            }
1337    
1338            protected void copyPreferences(
1339                    long userId, String sourcePortletId, String targetPortletId) {
1340    
1341                    Layout layout = getLayout();
1342    
1343                    try {
1344                            PortletPreferencesIds portletPreferencesIds =
1345                                    PortletPreferencesFactoryUtil.getPortletPreferencesIds(
1346                                            layout.getGroupId(), 0, layout, sourcePortletId, false);
1347    
1348                            javax.portlet.PortletPreferences sourcePortletPreferences =
1349                                    PortletPreferencesLocalServiceUtil.getStrictPreferences(
1350                                            portletPreferencesIds);
1351    
1352                            portletPreferencesIds =
1353                                    PortletPreferencesFactoryUtil.getPortletPreferencesIds(
1354                                            layout.getGroupId(), userId, layout, targetPortletId,
1355                                            false);
1356    
1357                            PortletPreferencesLocalServiceUtil.updatePreferences(
1358                                    portletPreferencesIds.getOwnerId(),
1359                                    portletPreferencesIds.getOwnerType(),
1360                                    portletPreferencesIds.getPlid(),
1361                                    portletPreferencesIds.getPortletId(), sourcePortletPreferences);
1362                    }
1363                    catch (Exception e) {
1364                    }
1365            }
1366    
1367            protected String getColumn(String portletId) {
1368                    String portletIdColumnId = StringPool.BLANK;
1369    
1370                    List<String> columnIds = getColumns();
1371    
1372                    for (String columnId : columnIds) {
1373                            String columnValue = getColumnValue(columnId);
1374    
1375                            String[] portletIds = StringUtil.split(columnValue);
1376    
1377                            for (String columnPortletId : portletIds) {
1378                                    if (columnPortletId.equals(portletId)) {
1379                                            return columnId;
1380                                    }
1381    
1382                                    if (Validator.isNull(portletIdColumnId) &&
1383                                            PortletConstants.hasIdenticalRootPortletId(
1384                                                    columnPortletId, portletId)) {
1385    
1386                                            portletIdColumnId = columnId;
1387                                    }
1388                            }
1389                    }
1390    
1391                    return portletIdColumnId;
1392            }
1393    
1394            protected List<String> getColumns() {
1395                    List<String> columns = new ArrayList<String>();
1396    
1397                    Layout layout = getLayout();
1398    
1399                    if (layout.isTypePortlet()) {
1400                            LayoutTemplate layoutTemplate = getLayoutTemplate();
1401    
1402                            columns.addAll(layoutTemplate.getColumns());
1403    
1404                            columns.addAll(getNestedColumns());
1405                    }
1406                    else if (layout.isTypePanel()) {
1407                            columns.add("panelSelectedPortlets");
1408                    }
1409    
1410                    return columns;
1411            }
1412    
1413            protected String getColumnValue(String columnId) {
1414                    if (hasUserPreferences() && isCustomizable() &&
1415                            !isColumnDisabled(columnId)) {
1416    
1417                            return getUserPreference(columnId);
1418                    }
1419    
1420                    return getTypeSettingsProperty(columnId);
1421            }
1422    
1423            protected long getCompanyId() {
1424                    Layout layout = getLayout();
1425    
1426                    return layout.getCompanyId();
1427            }
1428    
1429            protected LayoutTypePortletImpl getDefaultLayoutTypePortletImpl() {
1430                    if (!isCustomizedView()) {
1431                            return this;
1432                    }
1433    
1434                    LayoutTypePortletImpl defaultLayoutTypePortletImpl =
1435                            (LayoutTypePortletImpl)LayoutTypePortletFactoryUtil.create(
1436                                    getLayout());
1437    
1438                    defaultLayoutTypePortletImpl._embeddedPortlets = _embeddedPortlets;
1439                    defaultLayoutTypePortletImpl._layoutSetPrototypeLayout =
1440                            _layoutSetPrototypeLayout;
1441                    defaultLayoutTypePortletImpl._updatePermission = _updatePermission;
1442    
1443                    return defaultLayoutTypePortletImpl;
1444            }
1445    
1446            protected List<Portlet> getEmbeddedPortlets(
1447                    List<Portlet> columnPortlets, List<Portlet> staticPortlets) {
1448    
1449                    if (_embeddedPortlets != null) {
1450                            return _embeddedPortlets;
1451                    }
1452    
1453                    List<Portlet> portlets = new ArrayList<Portlet>();
1454    
1455                    Layout layout = getLayout();
1456    
1457                    List<PortletPreferences> portletPreferences =
1458                            PortletPreferencesLocalServiceUtil.getPortletPreferences(
1459                                    PortletKeys.PREFS_OWNER_ID_DEFAULT,
1460                                    PortletKeys.PREFS_OWNER_TYPE_LAYOUT, layout.getPlid());
1461    
1462                    if (isCustomizable() && hasUserPreferences()) {
1463                            portletPreferences = ListUtil.copy(portletPreferences);
1464    
1465                            portletPreferences.addAll(
1466                                    PortletPreferencesLocalServiceUtil.getPortletPreferences(
1467                                            _portalPreferences.getUserId(),
1468                                            PortletKeys.PREFS_OWNER_TYPE_USER, layout.getPlid()));
1469                    }
1470    
1471                    for (PortletPreferences portletPreference : portletPreferences) {
1472                            String portletId = portletPreference.getPortletId();
1473    
1474                            Portlet portlet = PortletLocalServiceUtil.getPortletById(
1475                                    getCompanyId(), portletId);
1476    
1477                            if (Validator.isNull(portletId) ||
1478                                    columnPortlets.contains(portlet) ||
1479                                    staticPortlets.contains(portlet) || !portlet.isReady() ||
1480                                    portlet.isUndeployedPortlet() || !portlet.isActive()) {
1481    
1482                                    continue;
1483                            }
1484    
1485                            if (portlet != null) {
1486                                    Portlet embeddedPortlet = portlet;
1487    
1488                                    if (portlet.isInstanceable()) {
1489    
1490                                            // Instanceable portlets do not need to be cloned because
1491                                            // they are already cloned. See the method getPortletById in
1492                                            // the class PortletLocalServiceImpl and how it references
1493                                            // the method getClonedInstance in the class PortletImpl.
1494    
1495                                    }
1496                                    else {
1497                                            embeddedPortlet = (Portlet)embeddedPortlet.clone();
1498                                    }
1499    
1500                                    // We set embedded portlets as static on order to avoid adding
1501                                    // the close and/or move icons.
1502    
1503                                    embeddedPortlet.setStatic(true);
1504    
1505                                    portlets.add(embeddedPortlet);
1506                            }
1507                    }
1508    
1509                    _embeddedPortlets = portlets;
1510    
1511                    return _embeddedPortlets;
1512            }
1513    
1514            protected List<String> getNestedColumns() {
1515                    String nestedColumnIds = getTypeSettingsProperty(
1516                            LayoutTypePortletConstants.NESTED_COLUMN_IDS);
1517    
1518                    return ListUtil.fromArray(StringUtil.split(nestedColumnIds));
1519            }
1520    
1521            protected long getPlid() {
1522                    Layout layout = getLayout();
1523    
1524                    return layout.getPlid();
1525            }
1526    
1527            protected String[] getStaticPortletIds(String position)
1528                    throws PortalException {
1529    
1530                    Layout layout = getLayout();
1531    
1532                    String selector1 = StringPool.BLANK;
1533    
1534                    Group group = layout.getGroup();
1535    
1536                    if (group.isUser()) {
1537                            selector1 = LayoutTypePortletConstants.STATIC_PORTLET_USER_SELECTOR;
1538                    }
1539                    else if (group.isOrganization()) {
1540                            selector1 =
1541                                    LayoutTypePortletConstants.STATIC_PORTLET_ORGANIZATION_SELECTOR;
1542                    }
1543                    else if (group.isRegularSite()) {
1544                            selector1 =
1545                                    LayoutTypePortletConstants.STATIC_PORTLET_REGULAR_SITE_SELECTOR;
1546                    }
1547    
1548                    String selector2 = layout.getFriendlyURL();
1549    
1550                    String[] portletIds = PropsUtil.getArray(
1551                            position, new Filter(selector1, selector2));
1552    
1553                    for (int i = 0; i < portletIds.length; i++) {
1554                            portletIds[i] = JS.getSafeName(portletIds[i]);
1555                    }
1556    
1557                    return portletIds;
1558            }
1559    
1560            protected List<Portlet> getStaticPortlets(String position)
1561                    throws PortalException {
1562    
1563                    String[] portletIds = getStaticPortletIds(position);
1564    
1565                    List<Portlet> portlets = new ArrayList<Portlet>();
1566    
1567                    for (String portletId : portletIds) {
1568                            if (Validator.isNull(portletId) ||
1569                                    hasNonstaticPortletId(portletId)) {
1570    
1571                                    continue;
1572                            }
1573    
1574                            Portlet portlet = PortletLocalServiceUtil.getPortletById(
1575                                    getCompanyId(), portletId);
1576    
1577                            if (portlet != null) {
1578                                    Portlet staticPortlet = portlet;
1579    
1580                                    if (portlet.isInstanceable()) {
1581    
1582                                            // Instanceable portlets do not need to be cloned because
1583                                            // they are already cloned. See the method getPortletById in
1584                                            // the class PortletLocalServiceImpl and how it references
1585                                            // the method getClonedInstance in the class PortletImpl.
1586    
1587                                    }
1588                                    else {
1589                                            staticPortlet = (Portlet)staticPortlet.clone();
1590                                    }
1591    
1592                                    staticPortlet.setStatic(true);
1593    
1594                                    if (position.startsWith("layout.static.portlets.start")) {
1595                                            staticPortlet.setStaticStart(true);
1596                                    }
1597    
1598                                    portlets.add(staticPortlet);
1599                            }
1600                    }
1601    
1602                    return portlets;
1603            }
1604    
1605            protected String getThemeId() {
1606                    String themeId = null;
1607    
1608                    try {
1609                            Layout layout = getLayout();
1610    
1611                            Theme theme = layout.getTheme();
1612    
1613                            if (theme != null) {
1614                                    themeId = theme.getThemeId();
1615                            }
1616                            else {
1617                                    themeId = layout.getThemeId();
1618                            }
1619                    }
1620                    catch (Exception e) {
1621                            _log.error(e, e);
1622                    }
1623    
1624                    return themeId;
1625            }
1626    
1627            protected String getUserPreference(String key) {
1628                    String value = StringPool.BLANK;
1629    
1630                    if (!hasUserPreferences()) {
1631                            return value;
1632                    }
1633    
1634                    value = _portalPreferences.getValue(
1635                            CustomizedPages.namespacePlid(getPlid()), key, StringPool.NULL);
1636    
1637                    if (!value.equals(StringPool.NULL)) {
1638                            return value;
1639                    }
1640    
1641                    value = getTypeSettingsProperty(key);
1642    
1643                    if (Validator.isNull(value)) {
1644                            return value;
1645                    }
1646    
1647                    List<String> newPortletIds = new ArrayList<String>();
1648    
1649                    PermissionChecker permissionChecker =
1650                            PermissionThreadLocal.getPermissionChecker();
1651    
1652                    String[] portletIds = StringUtil.split(value);
1653    
1654                    for (String portletId : portletIds) {
1655                            try {
1656                                    String rootPortletId = PortletConstants.getRootPortletId(
1657                                            portletId);
1658    
1659                                    if (!PortletPermissionUtil.contains(
1660                                                    permissionChecker, rootPortletId,
1661                                                    ActionKeys.ADD_TO_PAGE)) {
1662    
1663                                            continue;
1664                                    }
1665                            }
1666                            catch (Exception e) {
1667                                    _log.error(e, e);
1668                            }
1669    
1670                            String newPortletId = null;
1671    
1672                            boolean preferencesUniquePerLayout = false;
1673    
1674                            try {
1675                                    Portlet portlet = PortletLocalServiceUtil.getPortletById(
1676                                            getCompanyId(), portletId);
1677    
1678                                    preferencesUniquePerLayout =
1679                                            portlet.isPreferencesUniquePerLayout();
1680                            }
1681                            catch (SystemException se) {
1682                                    _log.error(se, se);
1683                            }
1684    
1685                            if (PortletConstants.hasInstanceId(portletId) ||
1686                                    preferencesUniquePerLayout) {
1687    
1688                                    String instanceId = null;
1689    
1690                                    if (PortletConstants.hasInstanceId(portletId)) {
1691                                            instanceId = PortletConstants.generateInstanceId();
1692                                    }
1693    
1694                                    newPortletId = PortletConstants.assemblePortletId(
1695                                            portletId, _portalPreferences.getUserId(), instanceId);
1696    
1697                                    copyPreferences(
1698                                            _portalPreferences.getUserId(), portletId, newPortletId);
1699                            }
1700                            else {
1701                                    newPortletId = portletId;
1702                            }
1703    
1704                            newPortletIds.add(newPortletId);
1705                    }
1706    
1707                    value = StringUtil.merge(newPortletIds);
1708    
1709                    setUserPreference(key, value);
1710    
1711                    return value;
1712            }
1713    
1714            protected boolean hasNonstaticPortletId(String portletId) {
1715                    LayoutTemplate layoutTemplate = getLayoutTemplate();
1716    
1717                    List<String> columns = layoutTemplate.getColumns();
1718    
1719                    for (int i = 0; i < columns.size(); i++) {
1720                            String columnId = columns.get(i);
1721    
1722                            if (hasNonstaticPortletId(columnId, portletId)) {
1723                                    return true;
1724                            }
1725                    }
1726    
1727                    return false;
1728            }
1729    
1730            protected boolean hasNonstaticPortletId(String columnId, String portletId) {
1731                    String columnValue = getColumnValue(columnId);
1732    
1733                    String[] columnValues = StringUtil.split(columnValue);
1734    
1735                    for (String nonstaticPortletId : columnValues) {
1736                            if (nonstaticPortletId.equals(portletId) ||
1737                                    PortletConstants.getRootPortletId(
1738                                            nonstaticPortletId).equals(portletId)) {
1739    
1740                                    return true;
1741                            }
1742                    }
1743    
1744                    return false;
1745            }
1746    
1747            protected boolean hasStaticPortletId(String columnId, String portletId)
1748                    throws PortalException {
1749    
1750                    String[] staticPortletIdsStart = getStaticPortletIds(
1751                            PropsKeys.LAYOUT_STATIC_PORTLETS_START + columnId);
1752    
1753                    String[] staticPortletIdsEnd = getStaticPortletIds(
1754                            PropsKeys.LAYOUT_STATIC_PORTLETS_END + columnId);
1755    
1756                    for (String staticPortletId : staticPortletIdsStart) {
1757                            if (staticPortletId.equals(portletId) ||
1758                                    PortletConstants.getRootPortletId(
1759                                            staticPortletId).equals(portletId)) {
1760    
1761                                    return true;
1762                            }
1763                    }
1764    
1765                    for (String staticPortletId : staticPortletIdsEnd) {
1766                            if (staticPortletId.equals(portletId) ||
1767                                    PortletConstants.getRootPortletId(
1768                                            staticPortletId).equals(portletId)) {
1769    
1770                                    return true;
1771                            }
1772                    }
1773    
1774                    return false;
1775            }
1776    
1777            protected boolean hasUserPreferences() {
1778                    if (_portalPreferences != null) {
1779                            return true;
1780                    }
1781    
1782                    return false;
1783            }
1784    
1785            protected boolean isLayoutSetPrototype() {
1786                    try {
1787                            Layout layout = getLayout();
1788    
1789                            LayoutSet layoutSet = layout.getLayoutSet();
1790    
1791                            Group group = layoutSet.getGroup();
1792    
1793                            return group.isLayoutSetPrototype();
1794                    }
1795                    catch (Exception e) {
1796                            _log.error(e, e);
1797                    }
1798    
1799                    return false;
1800            }
1801    
1802            protected void onRemoveFromLayout(String[] portletIds) {
1803                    Set<String> portletIdList = new HashSet<String>();
1804    
1805                    for (String portletId : portletIds) {
1806                            removeModesPortletId(portletId);
1807                            removeStatesPortletId(portletId);
1808    
1809                            portletIdList.add(portletId);
1810    
1811                            String rootPortletId = PortletConstants.getRootPortletId(portletId);
1812    
1813                            if (rootPortletId.equals(PortletKeys.NESTED_PORTLETS)) {
1814                                    String portletNamespace = PortalUtil.getPortletNamespace(
1815                                            portletId);
1816    
1817                                    UnicodeProperties typeSettingsProperties =
1818                                            getTypeSettingsProperties();
1819    
1820                                    for (Map.Entry<String, String> entry :
1821                                                    typeSettingsProperties.entrySet()) {
1822    
1823                                            String key = entry.getKey();
1824    
1825                                            if (!key.startsWith(portletNamespace)) {
1826                                                    continue;
1827                                            }
1828    
1829                                            String nestedPortletIds = entry.getValue();
1830    
1831                                            for (String nestedPortletId :
1832                                                            StringUtil.split(nestedPortletIds)) {
1833    
1834                                                    removeModesPortletId(nestedPortletId);
1835                                                    removeStatesPortletId(nestedPortletId);
1836    
1837                                                    portletIdList.add(nestedPortletId);
1838                                            }
1839                                    }
1840    
1841                                    removeNestedColumns(portletNamespace);
1842                            }
1843                    }
1844    
1845                    try {
1846                            PortletLocalServiceUtil.deletePortlets(
1847                                    getCompanyId(),
1848                                    portletIdList.toArray(new String[portletIdList.size()]),
1849                                    getPlid());
1850                    }
1851                    catch (PortalException pe) {
1852                            _log.error(pe, pe);
1853                    }
1854            }
1855    
1856            protected void setUserPreference(String key, String value) {
1857                    if (!hasUserPreferences()) {
1858                            return;
1859                    }
1860    
1861                    _portalPreferences.setValue(
1862                            CustomizedPages.namespacePlid(getPlid()), key, value);
1863    
1864                    _portalPreferences.setValue(
1865                            CustomizedPages.namespacePlid(getPlid()), _MODIFIED_DATE,
1866                            _dateFormat.format(new Date()));
1867            }
1868    
1869            private static final String _MODIFIED_DATE = "modifiedDate";
1870    
1871            private static final String _NULL_DATE = "00000000000000";
1872    
1873            private static Log _log = LogFactoryUtil.getLog(
1874                    LayoutTypePortletImpl.class);
1875    
1876            private static String _nestedPortletsNamespace;
1877    
1878            private boolean _customizedView;
1879            private Format _dateFormat = FastDateFormatFactoryUtil.getSimpleDateFormat(
1880                    PropsValues.INDEX_DATE_FORMAT_PATTERN);
1881            private transient List<Portlet> _embeddedPortlets;
1882            private boolean _enablePortletLayoutListener = true;
1883            private Layout _layoutSetPrototypeLayout;
1884            private PortalPreferences _portalPreferences;
1885            private boolean _updatePermission;
1886    
1887    }