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.service.impl;
016    
017    import com.liferay.portal.LARFileNameException;
018    import com.liferay.portal.LocaleException;
019    import com.liferay.portal.NoSuchLayoutException;
020    import com.liferay.portal.RequiredLayoutException;
021    import com.liferay.portal.SitemapChangeFrequencyException;
022    import com.liferay.portal.SitemapIncludeException;
023    import com.liferay.portal.SitemapPagePriorityException;
024    import com.liferay.portal.kernel.bean.BeanReference;
025    import com.liferay.portal.kernel.dao.orm.QueryUtil;
026    import com.liferay.portal.kernel.exception.PortalException;
027    import com.liferay.portal.kernel.exception.SystemException;
028    import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayInputStream;
029    import com.liferay.portal.kernel.lar.MissingReferences;
030    import com.liferay.portal.kernel.lar.PortletDataException;
031    import com.liferay.portal.kernel.lar.exportimportconfiguration.ExportImportConfigurationConstants;
032    import com.liferay.portal.kernel.lar.exportimportconfiguration.ExportImportConfigurationSettingsMapFactory;
033    import com.liferay.portal.kernel.systemevent.SystemEvent;
034    import com.liferay.portal.kernel.systemevent.SystemEventHierarchyEntry;
035    import com.liferay.portal.kernel.systemevent.SystemEventHierarchyEntryThreadLocal;
036    import com.liferay.portal.kernel.util.Constants;
037    import com.liferay.portal.kernel.util.ContentTypes;
038    import com.liferay.portal.kernel.util.FileUtil;
039    import com.liferay.portal.kernel.util.GetterUtil;
040    import com.liferay.portal.kernel.util.ListUtil;
041    import com.liferay.portal.kernel.util.LocaleUtil;
042    import com.liferay.portal.kernel.util.ParamUtil;
043    import com.liferay.portal.kernel.util.StringBundler;
044    import com.liferay.portal.kernel.util.StringPool;
045    import com.liferay.portal.kernel.util.StringUtil;
046    import com.liferay.portal.kernel.util.UnicodeProperties;
047    import com.liferay.portal.kernel.util.Validator;
048    import com.liferay.portal.kernel.workflow.WorkflowConstants;
049    import com.liferay.portal.lar.LayoutExporter;
050    import com.liferay.portal.lar.LayoutImporter;
051    import com.liferay.portal.lar.PortletExporter;
052    import com.liferay.portal.lar.PortletImporter;
053    import com.liferay.portal.lar.backgroundtask.BackgroundTaskContextMapFactory;
054    import com.liferay.portal.lar.backgroundtask.LayoutExportBackgroundTaskExecutor;
055    import com.liferay.portal.lar.backgroundtask.LayoutImportBackgroundTaskExecutor;
056    import com.liferay.portal.lar.backgroundtask.PortletExportBackgroundTaskExecutor;
057    import com.liferay.portal.lar.backgroundtask.PortletImportBackgroundTaskExecutor;
058    import com.liferay.portal.model.BackgroundTask;
059    import com.liferay.portal.model.ExportImportConfiguration;
060    import com.liferay.portal.model.Group;
061    import com.liferay.portal.model.GroupConstants;
062    import com.liferay.portal.model.Layout;
063    import com.liferay.portal.model.LayoutConstants;
064    import com.liferay.portal.model.LayoutFriendlyURL;
065    import com.liferay.portal.model.LayoutPrototype;
066    import com.liferay.portal.model.LayoutReference;
067    import com.liferay.portal.model.LayoutSet;
068    import com.liferay.portal.model.LayoutSetPrototype;
069    import com.liferay.portal.model.LayoutType;
070    import com.liferay.portal.model.LayoutTypePortlet;
071    import com.liferay.portal.model.PortletConstants;
072    import com.liferay.portal.model.ResourceConstants;
073    import com.liferay.portal.model.ResourcePermission;
074    import com.liferay.portal.model.SystemEventConstants;
075    import com.liferay.portal.model.User;
076    import com.liferay.portal.model.UserGroup;
077    import com.liferay.portal.model.impl.VirtualLayout;
078    import com.liferay.portal.service.ServiceContext;
079    import com.liferay.portal.service.base.LayoutLocalServiceBaseImpl;
080    import com.liferay.portal.util.PortalUtil;
081    import com.liferay.portal.util.PropsValues;
082    import com.liferay.portal.util.comparator.LayoutComparator;
083    import com.liferay.portal.util.comparator.LayoutPriorityComparator;
084    import com.liferay.portlet.documentlibrary.util.DLValidatorUtil;
085    import com.liferay.portlet.dynamicdatalists.RecordSetDuplicateRecordSetKeyException;
086    import com.liferay.portlet.dynamicdatamapping.StructureDuplicateStructureKeyException;
087    import com.liferay.portlet.mobiledevicerules.model.MDRRuleGroupInstance;
088    import com.liferay.portlet.sites.util.Sites;
089    import com.liferay.portlet.sites.util.SitesUtil;
090    
091    import java.io.File;
092    import java.io.IOException;
093    import java.io.InputStream;
094    import java.io.Serializable;
095    
096    import java.util.ArrayList;
097    import java.util.Date;
098    import java.util.HashMap;
099    import java.util.HashSet;
100    import java.util.LinkedHashSet;
101    import java.util.List;
102    import java.util.Locale;
103    import java.util.Map;
104    import java.util.Set;
105    
106    /**
107     * Provides the local service for accessing, adding, deleting, exporting,
108     * importing, and updating layouts.
109     *
110     * @author Brian Wing Shun Chan
111     * @author Jorge Ferrer
112     * @author Joel Kozikowski
113     * @author Charles May
114     * @author Raymond Aug??
115     * @author Jorge Ferrer
116     * @author Bruno Farache
117     * @author Vilmos Papp
118     * @author James Lefeu
119     * @author Tibor Lipusz
120     */
121    public class LayoutLocalServiceImpl extends LayoutLocalServiceBaseImpl {
122    
123            /**
124             * Returns the object counter's name.
125             *
126             * @param  groupId the primary key of the group
127             * @param  privateLayout whether layout is private to the group
128             * @return the object counter's name
129             */
130            public static String getCounterName(long groupId, boolean privateLayout) {
131                    StringBundler sb = new StringBundler(5);
132    
133                    sb.append(Layout.class.getName());
134                    sb.append(StringPool.POUND);
135                    sb.append(groupId);
136                    sb.append(StringPool.POUND);
137                    sb.append(privateLayout);
138    
139                    return sb.toString();
140            }
141    
142            /**
143             * Adds a layout.
144             *
145             * <p>
146             * This method handles the creation of the layout including its resources,
147             * metadata, and internal data structures. It is not necessary to make
148             * subsequent calls to any methods to setup default groups, resources, ...
149             * etc.
150             * </p>
151             *
152             * @param      userId the primary key of the user
153             * @param      groupId the primary key of the group
154             * @param      privateLayout whether the layout is private to the group
155             * @param      parentLayoutId the primary key of the parent layout
156             *             (optionally {@link
157             *             com.liferay.portal.model.LayoutConstants#DEFAULT_PARENT_LAYOUT_ID})
158             * @param      nameMap the layout's locales and localized names
159             * @param      titleMap the layout's locales and localized titles
160             * @param      descriptionMap the layout's locales and localized
161             *             descriptions
162             * @param      keywordsMap the layout's locales and localized keywords
163             * @param      robotsMap the layout's locales and localized robots
164             * @param      type the layout's type (optionally {@link
165             *             com.liferay.portal.model.LayoutConstants#TYPE_PORTLET}). The
166             *             possible types can be found in {@link
167             *             com.liferay.portal.model.LayoutConstants}.
168             * @param      hidden whether the layout is hidden
169             * @param      friendlyURL the layout's friendly URL (optionally {@link
170             *             com.liferay.portal.util.PropsValues#DEFAULT_USER_PRIVATE_LAYOUT_FRIENDLY_URL}
171             *             or {@link
172             *             com.liferay.portal.util.PropsValues#DEFAULT_USER_PUBLIC_LAYOUT_FRIENDLY_URL}).
173             *             The default values can be overridden in
174             *             <code>portal-ext.properties</code> by specifying new values
175             *             for the corresponding properties defined in {@link
176             *             com.liferay.portal.util.PropsValues}. To see how the URL is
177             *             normalized when accessed, see {@link
178             *             com.liferay.portal.kernel.util.FriendlyURLNormalizerUtil#normalize(
179             *             String)}.
180             * @param      serviceContext the service context to be applied. Must set
181             *             the UUID for the layout. Can set the creation date,
182             *             modification date and the expando bridge attributes for the
183             *             layout. For layouts that belong to a layout set prototype, an
184             *             attribute named <code>layoutUpdateable</code> can be set to
185             *             specify whether site administrators can modify this page
186             *             within their site. For layouts that are created from a layout
187             *             prototype, attributes named <code>layoutPrototypeUuid</code>
188             *             and <code>layoutPrototypeLinkedEnabled</code> can be
189             *             specified to provide the unique identifier of the source
190             *             prototype and a boolean to determine whether a link to it
191             *             should be enabled to activate propagation of changes made to
192             *             the linked page in the prototype.
193             * @return     the layout
194             * @throws     PortalException if a group or user with the primary key could
195             *             not be found, if layout values were invalid, or if a portal
196             *             exception occurred
197             * @deprecated As of 6.2.0, replaced by {@link #addLayout(long, long,
198             *             boolean, long, Map, Map, Map, Map, Map, String, String,
199             *             boolean, Map, ServiceContext)}
200             */
201            @Deprecated
202            @Override
203            public Layout addLayout(
204                            long userId, long groupId, boolean privateLayout,
205                            long parentLayoutId, Map<Locale, String> nameMap,
206                            Map<Locale, String> titleMap, Map<Locale, String> descriptionMap,
207                            Map<Locale, String> keywordsMap, Map<Locale, String> robotsMap,
208                            String type, boolean hidden, String friendlyURL,
209                            ServiceContext serviceContext)
210                    throws PortalException {
211    
212                    Map<Locale, String> friendlyURLMap = new HashMap<Locale, String>();
213    
214                    friendlyURLMap.put(LocaleUtil.getSiteDefault(), friendlyURL);
215    
216                    return addLayout(
217                            userId, groupId, privateLayout, parentLayoutId, nameMap, titleMap,
218                            descriptionMap, keywordsMap, robotsMap, type, StringPool.BLANK,
219                            hidden, friendlyURLMap, serviceContext);
220            }
221    
222            /**
223             * Adds a layout with additional parameters.
224             *
225             * <p>
226             * This method handles the creation of the layout including its resources,
227             * metadata, and internal data structures. It is not necessary to make
228             * subsequent calls to any methods to setup default groups, resources, ...
229             * etc.
230             * </p>
231             *
232             * @param  userId the primary key of the user
233             * @param  groupId the primary key of the group
234             * @param  privateLayout whether the layout is private to the group
235             * @param  parentLayoutId the primary key of the parent layout (optionally
236             *         {@link
237             *         com.liferay.portal.model.LayoutConstants#DEFAULT_PARENT_LAYOUT_ID})
238             * @param  nameMap the layout's locales and localized names
239             * @param  titleMap the layout's locales and localized titles
240             * @param  descriptionMap the layout's locales and localized descriptions
241             * @param  keywordsMap the layout's locales and localized keywords
242             * @param  robotsMap the layout's locales and localized robots
243             * @param  type the layout's type (optionally {@link
244             *         com.liferay.portal.model.LayoutConstants#TYPE_PORTLET}). The
245             *         possible types can be found in {@link
246             *         com.liferay.portal.model.LayoutConstants}.
247             * @param  typeSettings the settings to load the unicode properties object.
248             *         See {@link com.liferay.portal.kernel.util.UnicodeProperties
249             *         #fastLoad(String)}.
250             * @param  hidden whether the layout is hidden
251             * @param  friendlyURLMap the layout's locales and localized friendly URLs.
252             *         To see how the URL is normalized when accessed, see {@link
253             *         com.liferay.portal.kernel.util.FriendlyURLNormalizerUtil#normalize(
254             *         String)}.
255             * @param  serviceContext the service context to be applied. Must set the
256             *         UUID for the layout. Can set the creation date, modification
257             *         date, and expando bridge attributes for the layout. For layouts
258             *         that belong to a layout set prototype, an attribute named
259             *         <code>layoutUpdateable</code> can be set to specify whether site
260             *         administrators can modify this page within their site. For
261             *         layouts that are created from a layout prototype, attributes
262             *         named <code>layoutPrototypeUuid</code> and
263             *         <code>layoutPrototypeLinkedEnabled</code> can be specified to
264             *         provide the unique identifier of the source prototype and a
265             *         boolean to determine whether a link to it should be enabled to
266             *         activate propagation of changes made to the linked page in the
267             *         prototype.
268             * @return the layout
269             * @throws PortalException if a group or user with the primary key could not
270             *         be found, if layout values were invalid, or if a portal exception
271             *         occurred
272             */
273            @Override
274            public Layout addLayout(
275                            long userId, long groupId, boolean privateLayout,
276                            long parentLayoutId, Map<Locale, String> nameMap,
277                            Map<Locale, String> titleMap, Map<Locale, String> descriptionMap,
278                            Map<Locale, String> keywordsMap, Map<Locale, String> robotsMap,
279                            String type, String typeSettings, boolean hidden,
280                            Map<Locale, String> friendlyURLMap, ServiceContext serviceContext)
281                    throws PortalException {
282    
283                    // Layout
284    
285                    User user = userPersistence.findByPrimaryKey(userId);
286                    long layoutId = getNextLayoutId(groupId, privateLayout);
287                    parentLayoutId = layoutLocalServiceHelper.getParentLayoutId(
288                            groupId, privateLayout, parentLayoutId);
289                    String name = nameMap.get(LocaleUtil.getSiteDefault());
290                    friendlyURLMap = layoutLocalServiceHelper.getFriendlyURLMap(
291                            groupId, privateLayout, layoutId, name, friendlyURLMap);
292    
293                    String friendlyURL = friendlyURLMap.get(LocaleUtil.getSiteDefault());
294    
295                    int priority = layoutLocalServiceHelper.getNextPriority(
296                            groupId, privateLayout, parentLayoutId, null, -1);
297    
298                    layoutLocalServiceHelper.validate(
299                            groupId, privateLayout, layoutId, parentLayoutId, name, type,
300                            hidden, friendlyURLMap);
301    
302                    Date now = new Date();
303    
304                    long plid = counterLocalService.increment();
305    
306                    Layout layout = layoutPersistence.create(plid);
307    
308                    layout.setUuid(serviceContext.getUuid());
309                    layout.setGroupId(groupId);
310                    layout.setCompanyId(user.getCompanyId());
311                    layout.setUserId(user.getUserId());
312                    layout.setUserName(user.getFullName());
313                    layout.setCreateDate(serviceContext.getCreateDate(now));
314                    layout.setModifiedDate(serviceContext.getModifiedDate(now));
315                    layout.setPrivateLayout(privateLayout);
316                    layout.setLayoutId(layoutId);
317                    layout.setParentLayoutId(parentLayoutId);
318                    layout.setNameMap(nameMap);
319                    layout.setTitleMap(titleMap);
320                    layout.setDescriptionMap(descriptionMap);
321                    layout.setKeywordsMap(keywordsMap);
322                    layout.setRobotsMap(robotsMap);
323                    layout.setType(type);
324                    layout.setHidden(hidden);
325                    layout.setFriendlyURL(friendlyURL);
326                    layout.setPriority(priority);
327    
328                    boolean layoutUpdateable = ParamUtil.getBoolean(
329                            serviceContext, Sites.LAYOUT_UPDATEABLE, true);
330    
331                    UnicodeProperties typeSettingsProperties = new UnicodeProperties();
332    
333                    typeSettingsProperties.fastLoad(typeSettings);
334    
335                    if (!layoutUpdateable) {
336                            typeSettingsProperties.put(
337                                    Sites.LAYOUT_UPDATEABLE, String.valueOf(layoutUpdateable));
338                    }
339    
340                    if (privateLayout) {
341                            typeSettingsProperties.put(
342                                    "privateLayout", String.valueOf(privateLayout));
343                    }
344    
345                    validateTypeSettingsProperties(typeSettingsProperties);
346    
347                    layout.setTypeSettingsProperties(typeSettingsProperties);
348    
349                    String layoutPrototypeUuid = ParamUtil.getString(
350                            serviceContext, "layoutPrototypeUuid");
351                    boolean layoutPrototypeLinkEnabled = ParamUtil.getBoolean(
352                            serviceContext, "layoutPrototypeLinkEnabled",
353                            PropsValues.LAYOUT_PROTOTYPE_LINK_ENABLED_DEFAULT);
354    
355                    if (Validator.isNotNull(layoutPrototypeUuid)) {
356                            layout.setLayoutPrototypeUuid(layoutPrototypeUuid);
357                            layout.setLayoutPrototypeLinkEnabled(layoutPrototypeLinkEnabled);
358                    }
359    
360                    if (type.equals(LayoutConstants.TYPE_PORTLET)) {
361                            LayoutTypePortlet layoutTypePortlet =
362                                    (LayoutTypePortlet)layout.getLayoutType();
363    
364                            if (Validator.isNull(layoutTypePortlet.getLayoutTemplateId())) {
365                                    layoutTypePortlet.setLayoutTemplateId(
366                                            0, PropsValues.LAYOUT_DEFAULT_TEMPLATE_ID, false);
367                            }
368                    }
369    
370                    layout.setExpandoBridgeAttributes(serviceContext);
371    
372                    layoutPersistence.update(layout);
373    
374                    if (Validator.isNotNull(layoutPrototypeUuid) &&
375                            !layoutPrototypeLinkEnabled) {
376    
377                            LayoutPrototype layoutPrototype =
378                                    layoutPrototypeLocalService.
379                                            getLayoutPrototypeByUuidAndCompanyId(
380                                                    layoutPrototypeUuid, layout.getCompanyId());
381    
382                            try {
383                                    SitesUtil.applyLayoutPrototype(
384                                            layoutPrototype, layout, layoutPrototypeLinkEnabled);
385                            }
386                            catch (PortalException pe) {
387                                    throw pe;
388                            }
389                            catch (SystemException se) {
390                                    throw se;
391                            }
392                            catch (Exception e) {
393                                    throw new SystemException(e);
394                            }
395                    }
396    
397                    // Resources
398    
399                    boolean addGroupPermissions = true;
400    
401                    Group group = groupLocalService.getGroup(groupId);
402    
403                    if (privateLayout && group.isUser()) {
404                            addGroupPermissions = false;
405                    }
406    
407                    boolean addGuestPermissions = false;
408    
409                    if (!privateLayout ||
410                            type.equals(LayoutConstants.TYPE_CONTROL_PANEL) ||
411                            group.isLayoutSetPrototype()) {
412    
413                            addGuestPermissions = true;
414                    }
415    
416                    resourceLocalService.addResources(
417                            user.getCompanyId(), groupId, user.getUserId(),
418                            Layout.class.getName(), layout.getPlid(), false,
419                            addGroupPermissions, addGuestPermissions);
420    
421                    // Group
422    
423                    groupLocalService.updateSite(groupId, true);
424    
425                    // Layout friendly URLs
426    
427                    layoutFriendlyURLLocalService.updateLayoutFriendlyURLs(
428                            user.getUserId(), user.getCompanyId(), groupId, plid, privateLayout,
429                            friendlyURLMap, serviceContext);
430    
431                    // Layout set
432    
433                    layoutSetLocalService.updatePageCount(groupId, privateLayout);
434    
435                    LayoutSet layoutSet = layoutSetPersistence.findByG_P(
436                            groupId, privateLayout);
437    
438                    layout.setLayoutSet(layoutSet);
439    
440                    // Asset
441    
442                    updateAsset(
443                            userId, layout, serviceContext.getAssetCategoryIds(),
444                            serviceContext.getAssetTagNames());
445    
446                    // Message boards
447    
448                    if (PropsValues.LAYOUT_COMMENTS_ENABLED) {
449                            mbMessageLocalService.addDiscussionMessage(
450                                    userId, user.getFullName(), groupId, Layout.class.getName(),
451                                    plid, WorkflowConstants.ACTION_PUBLISH);
452                    }
453    
454                    return layout;
455            }
456    
457            /**
458             * Adds a layout with single entry maps for name, title, and description to
459             * the default locale.
460             *
461             * <p>
462             * This method handles the creation of the layout including its resources,
463             * metadata, and internal data structures. It is not necessary to make
464             * subsequent calls to any methods to setup default groups, resources, ...
465             * etc.
466             * </p>
467             *
468             * @param  userId the primary key of the user
469             * @param  groupId the primary key of the group
470             * @param  privateLayout whether the layout is private to the group
471             * @param  parentLayoutId the primary key of the parent layout (optionally
472             *         {@link
473             *         com.liferay.portal.model.LayoutConstants#DEFAULT_PARENT_LAYOUT_ID}).
474             *         The possible values can be found in {@link
475             *         com.liferay.portal.model.LayoutConstants}.
476             * @param  name the layout's name (optionally {@link
477             *         com.liferay.portal.util.PropsValues#DEFAULT_USER_PRIVATE_LAYOUT_NAME}
478             *         or {@link
479             *         com.liferay.portal.util.PropsValues#DEFAULT_USER_PUBLIC_LAYOUT_NAME}).
480             *         The default values can be overridden in
481             *         <code>portal-ext.properties</code> by specifying new values for
482             *         the corresponding properties defined in {@link
483             *         com.liferay.portal.util.PropsValues}
484             * @param  title the layout's title
485             * @param  description the layout's description
486             * @param  type the layout's type (optionally {@link
487             *         com.liferay.portal.model.LayoutConstants#TYPE_PORTLET}). The
488             *         possible types can be found in {@link
489             *         com.liferay.portal.model.LayoutConstants}.
490             * @param  hidden whether the layout is hidden
491             * @param  friendlyURL the friendly URL of the layout (optionally {@link
492             *         com.liferay.portal.util.PropsValues#DEFAULT_USER_PRIVATE_LAYOUT_FRIENDLY_URL}
493             *         or {@link
494             *         com.liferay.portal.util.PropsValues#DEFAULT_USER_PUBLIC_LAYOUT_FRIENDLY_URL}).
495             *         The default values can be overridden in
496             *         <code>portal-ext.properties</code> by specifying new values for
497             *         the corresponding properties defined in {@link
498             *         com.liferay.portal.util.PropsValues}. To see how the URL is
499             *         normalized when accessed, see {@link
500             *         com.liferay.portal.kernel.util.FriendlyURLNormalizerUtil#normalize(
501             *         String)}.
502             * @param  serviceContext the service context to be applied. Must set the
503             *         UUID for the layout. Can set the creation date and modification
504             *         date for the layout. For layouts that belong to a layout set
505             *         prototype, an attribute named <code>layoutUpdateable</code> can
506             *         be set to specify whether site administrators can modify this
507             *         page within their site.
508             * @return the layout
509             * @throws PortalException if a group or user with the primary key could not
510             *         be found, or if a portal exception occurred
511             */
512            @Override
513            public Layout addLayout(
514                            long userId, long groupId, boolean privateLayout,
515                            long parentLayoutId, String name, String title, String description,
516                            String type, boolean hidden, String friendlyURL,
517                            ServiceContext serviceContext)
518                    throws PortalException {
519    
520                    Locale locale = LocaleUtil.getSiteDefault();
521    
522                    Map<Locale, String> nameMap = new HashMap<Locale, String>();
523    
524                    nameMap.put(locale, name);
525    
526                    Map<Locale, String> titleMap = new HashMap<Locale, String>();
527    
528                    titleMap.put(locale, title);
529    
530                    Map<Locale, String> descriptionMap = new HashMap<Locale, String>();
531    
532                    descriptionMap.put(locale, description);
533    
534                    Map<Locale, String> friendlyURLMap = new HashMap<Locale, String>();
535    
536                    friendlyURLMap.put(LocaleUtil.getSiteDefault(), friendlyURL);
537    
538                    return addLayout(
539                            userId, groupId, privateLayout, parentLayoutId, nameMap, titleMap,
540                            descriptionMap, new HashMap<Locale, String>(),
541                            new HashMap<Locale, String>(), type, StringPool.BLANK, hidden,
542                            friendlyURLMap, serviceContext);
543            }
544    
545            /**
546             * Deletes the layout, its child layouts, and its associated resources.
547             *
548             * @param  layout the layout
549             * @param  updateLayoutSet whether the layout set's page counter needs to be
550             *         updated
551             * @param  serviceContext the service context to be applied
552             * @throws PortalException if a portal exception occurred
553             */
554            @Override
555            @SystemEvent(
556                    action = SystemEventConstants.ACTION_SKIP,
557                    type = SystemEventConstants.TYPE_DELETE)
558            public void deleteLayout(
559                            Layout layout, boolean updateLayoutSet,
560                            ServiceContext serviceContext)
561                    throws PortalException {
562    
563                    // First layout validation
564    
565                    if (layout.getParentLayoutId() ==
566                                    LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
567    
568                            List<Layout> rootLayouts = layoutPersistence.findByG_P_P(
569                                    layout.getGroupId(), layout.isPrivateLayout(),
570                                    LayoutConstants.DEFAULT_PARENT_LAYOUT_ID, 0, 2);
571    
572                            if (rootLayouts.size() > 1) {
573                                    Layout firstLayout = rootLayouts.get(0);
574    
575                                    if (firstLayout.getLayoutId() == layout.getLayoutId()) {
576                                            Layout secondLayout = rootLayouts.get(1);
577    
578                                            layoutLocalServiceHelper.validateFirstLayout(secondLayout);
579                                    }
580                            }
581                    }
582    
583                    // Child layouts
584    
585                    List<Layout> childLayouts = layoutPersistence.findByG_P_P(
586                            layout.getGroupId(), layout.isPrivateLayout(),
587                            layout.getLayoutId());
588    
589                    for (Layout childLayout : childLayouts) {
590                            layoutLocalService.deleteLayout(
591                                    childLayout, updateLayoutSet, serviceContext);
592                    }
593    
594                    // Layout friendly URLs
595    
596                    layoutFriendlyURLLocalService.deleteLayoutFriendlyURLs(
597                            layout.getPlid());
598    
599                    // Portlet preferences
600    
601                    portletPreferencesLocalService.deletePortletPreferencesByPlid(
602                            layout.getPlid());
603    
604                    // Subscriptions
605    
606                    subscriptionLocalService.deleteSubscriptions(
607                            layout.getCompanyId(), Layout.class.getName(), layout.getPlid());
608    
609                    // Asset
610    
611                    assetEntryLocalService.deleteEntry(
612                            Layout.class.getName(), layout.getPlid());
613    
614                    // Ratings
615    
616                    ratingsStatsLocalService.deleteStats(
617                            Layout.class.getName(), layout.getPlid());
618    
619                    // Mobile device rules
620    
621                    long layoutClassNameId = classNameLocalService.getClassNameId(
622                            Layout.class);
623    
624                    List<MDRRuleGroupInstance> mdrRuleGroupInstances =
625                            mdrRuleGroupInstancePersistence.findByC_C(
626                                    layoutClassNameId, layout.getPlid());
627    
628                    for (MDRRuleGroupInstance mdrRuleGroupInstance :
629                                    mdrRuleGroupInstances) {
630    
631                            mdrRuleGroupInstanceLocalService.deleteMDRRuleGroupInstance(
632                                    mdrRuleGroupInstance);
633                    }
634    
635                    // Message boards
636    
637                    mbMessageLocalService.deleteDiscussionMessages(
638                            Layout.class.getName(), layout.getPlid());
639    
640                    // Journal articles
641    
642                    journalArticleLocalService.deleteLayoutArticleReferences(
643                            layout.getGroupId(), layout.getUuid());
644    
645                    // Journal content searches
646    
647                    journalContentSearchLocalService.deleteLayoutContentSearches(
648                            layout.getGroupId(), layout.isPrivateLayout(),
649                            layout.getLayoutId());
650    
651                    // Expando
652    
653                    expandoRowLocalService.deleteRows(layout.getPlid());
654    
655                    // Icon
656    
657                    imageLocalService.deleteImage(layout.getIconImageId());
658    
659                    // Scope group
660    
661                    Group scopeGroup = layout.getScopeGroup();
662    
663                    if (scopeGroup != null) {
664                            groupLocalService.deleteGroup(scopeGroup.getGroupId());
665                    }
666    
667                    // Resources
668    
669                    String primKey =
670                            layout.getPlid() + PortletConstants.LAYOUT_SEPARATOR + "%";
671    
672                    List<ResourcePermission> resourcePermissions =
673                            resourcePermissionPersistence.findByC_LikeP(
674                                    layout.getCompanyId(), primKey);
675    
676                    for (ResourcePermission resourcePermission : resourcePermissions) {
677                            resourcePermissionLocalService.deleteResourcePermission(
678                                    resourcePermission);
679                    }
680    
681                    resourceLocalService.deleteResource(
682                            layout.getCompanyId(), Layout.class.getName(),
683                            ResourceConstants.SCOPE_INDIVIDUAL, layout.getPlid());
684    
685                    // Layout
686    
687                    layoutPersistence.remove(layout);
688    
689                    // Layout set
690    
691                    if (updateLayoutSet) {
692                            layoutSetLocalService.updatePageCount(
693                                    layout.getGroupId(), layout.isPrivateLayout());
694                    }
695    
696                    // System event
697    
698                    SystemEventHierarchyEntry systemEventHierarchyEntry =
699                            SystemEventHierarchyEntryThreadLocal.peek();
700    
701                    if ((systemEventHierarchyEntry != null) &&
702                            systemEventHierarchyEntry.hasTypedModel(
703                                    Layout.class.getName(), layout.getPlid())) {
704    
705                            systemEventHierarchyEntry.setExtraDataValue(
706                                    "privateLayout", StringUtil.valueOf(layout.isPrivateLayout()));
707                    }
708            }
709    
710            /**
711             * Deletes the layout with the primary key, also deleting the layout's child
712             * layouts, and associated resources.
713             *
714             * @param  groupId the primary key of the group
715             * @param  privateLayout whether the layout is private to the group
716             * @param  layoutId the primary key of the layout
717             * @param  serviceContext the service context to be applied
718             * @throws PortalException if a matching layout could not be found , or if
719             *         some other portal exception occurred
720             */
721            @Override
722            public void deleteLayout(
723                            long groupId, boolean privateLayout, long layoutId,
724                            ServiceContext serviceContext)
725                    throws PortalException {
726    
727                    Layout layout = layoutPersistence.findByG_P_L(
728                            groupId, privateLayout, layoutId);
729    
730                    layoutLocalService.deleteLayout(layout, true, serviceContext);
731            }
732    
733            /**
734             * Deletes the layout with the plid, also deleting the layout's child
735             * layouts, and associated resources.
736             *
737             * @param  plid the primary key of the layout
738             * @param  serviceContext the service context to be applied
739             * @throws PortalException if a layout with the primary key could not be
740             *         found , or if some other portal exception occurred
741             */
742            @Override
743            public void deleteLayout(long plid, ServiceContext serviceContext)
744                    throws PortalException {
745    
746                    Layout layout = layoutPersistence.findByPrimaryKey(plid);
747    
748                    layoutLocalService.deleteLayout(layout, true, serviceContext);
749            }
750    
751            /**
752             * Deletes the group's private or non-private layouts, also deleting the
753             * layouts' child layouts, and associated resources.
754             *
755             * @param  groupId the primary key of the group
756             * @param  privateLayout whether the layout is private to the group
757             * @param  serviceContext the service context to be applied. The parent
758             *         layout set's page count will be updated by default, unless an
759             *         attribute named <code>updatePageCount</code> is set to
760             *         <code>false</code>.
761             * @throws PortalException if a group with the primary key could not be
762             *         found or if a layout set for the group and privacy could not be
763             *         found
764             */
765            @Override
766            public void deleteLayouts(
767                            long groupId, boolean privateLayout, ServiceContext serviceContext)
768                    throws PortalException {
769    
770                    // Layouts
771    
772                    List<Layout> layouts = layoutPersistence.findByG_P_P(
773                            groupId, privateLayout, LayoutConstants.DEFAULT_PARENT_LAYOUT_ID,
774                            QueryUtil.ALL_POS, QueryUtil.ALL_POS,
775                            new LayoutPriorityComparator(false));
776    
777                    for (Layout layout : layouts) {
778                            try {
779                                    layoutLocalService.deleteLayout(layout, false, serviceContext);
780                            }
781                            catch (NoSuchLayoutException nsle) {
782                            }
783                    }
784    
785                    // Layout set
786    
787                    if (GetterUtil.getBoolean(
788                                    serviceContext.getAttribute("updatePageCount"), true)) {
789    
790                            layoutSetLocalService.updatePageCount(groupId, privateLayout);
791                    }
792    
793                    // Counter
794    
795                    counterLocalService.reset(getCounterName(groupId, privateLayout));
796            }
797    
798            /**
799             * Exports layouts with the primary keys and criteria as a byte array.
800             *
801             * @param  groupId the primary key of the group
802             * @param  privateLayout whether the layout is private to the group
803             * @param  layoutIds the primary keys of the layouts to be exported
804             * @param  parameterMap the mapping of parameters indicating which
805             *         information to export. For information on the keys used in the
806             *         map see {@link
807             *         com.liferay.portal.kernel.lar.PortletDataHandlerKeys}.
808             * @param  startDate the export's start date
809             * @param  endDate the export's end date
810             * @return the layouts as a byte array
811             * @throws PortalException if a group or any layout with the primary key
812             *         could not be found, or if some other portal exception occurred
813             */
814            @Override
815            public byte[] exportLayouts(
816                            long groupId, boolean privateLayout, long[] layoutIds,
817                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
818                    throws PortalException {
819    
820                    File file = exportLayoutsAsFile(
821                            groupId, privateLayout, layoutIds, parameterMap, startDate,
822                            endDate);
823    
824                    try {
825                            return FileUtil.getBytes(file);
826                    }
827                    catch (IOException ioe) {
828                            throw new SystemException(ioe);
829                    }
830                    finally {
831                            file.delete();
832                    }
833            }
834    
835            /**
836             * Exports all layouts that match the criteria as a byte array.
837             *
838             * @param  groupId the primary key of the group
839             * @param  privateLayout whether the layout is private to the group
840             * @param  parameterMap the mapping of parameters indicating which
841             *         information to export. For information on the keys used in the
842             *         map see {@link
843             *         com.liferay.portal.kernel.lar.PortletDataHandlerKeys}.
844             * @param  startDate the export's start date
845             * @param  endDate the export's end date
846             * @return the layout as a byte array
847             * @throws PortalException if a group with the primary key could not be
848             *         found or if some other portal exception occurred
849             */
850            @Override
851            public byte[] exportLayouts(
852                            long groupId, boolean privateLayout,
853                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
854                    throws PortalException {
855    
856                    return exportLayouts(
857                            groupId, privateLayout, null, parameterMap, startDate, endDate);
858            }
859    
860            /**
861             * Exports the layouts that match the primary keys and criteria as a file.
862             *
863             * @param  groupId the primary key of the group
864             * @param  privateLayout whether the layout is private to the group
865             * @param  layoutIds the primary keys of the layouts to be exported
866             *         (optionally <code>null</code>)
867             * @param  parameterMap the mapping of parameters indicating which
868             *         information to export. For information on the keys used in the
869             *         map see {@link
870             *         com.liferay.portal.kernel.lar.PortletDataHandlerKeys}.
871             * @param  startDate the export's start date
872             * @param  endDate the export's end date
873             * @return the layouts as a File
874             * @throws PortalException if a group or any layout with the primary key
875             *         could not be found, or if some other portal exception occurred
876             */
877            @Override
878            public File exportLayoutsAsFile(
879                            long groupId, boolean privateLayout, long[] layoutIds,
880                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
881                    throws PortalException {
882    
883                    try {
884                            LayoutExporter layoutExporter = LayoutExporter.getInstance();
885    
886                            return layoutExporter.exportLayoutsAsFile(
887                                    groupId, privateLayout, layoutIds, parameterMap, startDate,
888                                    endDate);
889                    }
890                    catch (PortalException pe) {
891                            throw pe;
892                    }
893                    catch (SystemException se) {
894                            throw se;
895                    }
896                    catch (Exception e) {
897                            throw new SystemException(e);
898                    }
899            }
900    
901            @Override
902            public long exportLayoutsAsFileInBackground(
903                            long userId, ExportImportConfiguration exportImportConfiguration)
904                    throws PortalException {
905    
906                    if (!DLValidatorUtil.isValidName(exportImportConfiguration.getName())) {
907                            throw new LARFileNameException(exportImportConfiguration.getName());
908                    }
909    
910                    Map<String, Serializable> taskContextMap =
911                            new HashMap<String, Serializable>();
912    
913                    taskContextMap.put(Constants.CMD, Constants.EXPORT);
914                    taskContextMap.put(
915                            "exportImportConfigurationId",
916                            exportImportConfiguration.getExportImportConfigurationId());
917    
918                    BackgroundTask backgroundTask =
919                            backgroundTaskLocalService.addBackgroundTask(
920                                    userId, exportImportConfiguration.getGroupId(),
921                                    exportImportConfiguration.getName(), null,
922                                    LayoutExportBackgroundTaskExecutor.class, taskContextMap,
923                                    new ServiceContext());
924    
925                    return backgroundTask.getBackgroundTaskId();
926            }
927    
928            @Override
929            public long exportLayoutsAsFileInBackground(
930                            long userId, long exportImportConfigurationId)
931                    throws PortalException {
932    
933                    ExportImportConfiguration exportImportConfiguration =
934                            exportImportConfigurationLocalService.getExportImportConfiguration(
935                                    exportImportConfigurationId);
936    
937                    return exportLayoutsAsFileInBackground(
938                            userId, exportImportConfiguration);
939            }
940    
941            @Override
942            public long exportLayoutsAsFileInBackground(
943                            long userId, String taskName, long groupId, boolean privateLayout,
944                            long[] layoutIds, Map<String, String[]> parameterMap,
945                            Date startDate, Date endDate)
946                    throws PortalException {
947    
948                    User user = userPersistence.findByPrimaryKey(userId);
949    
950                    Map<String, Serializable> settingsMap =
951                            ExportImportConfigurationSettingsMapFactory.buildSettingsMap(
952                                    userId, groupId, privateLayout, layoutIds, parameterMap,
953                                    startDate, endDate, user.getLocale(), user.getTimeZone());
954    
955                    ServiceContext serviceContext = new ServiceContext();
956    
957                    ExportImportConfiguration exportImportConfiguration =
958                            exportImportConfigurationLocalService.addExportImportConfiguration(
959                                    userId, groupId, taskName, StringPool.BLANK,
960                                    ExportImportConfigurationConstants.TYPE_EXPORT_LAYOUT,
961                                    settingsMap, WorkflowConstants.STATUS_DRAFT, serviceContext);
962    
963                    return exportLayoutsAsFileInBackground(
964                            userId, exportImportConfiguration);
965            }
966    
967            /**
968             * @deprecated As of 7.0.0, replaced by {@link
969             *             #exportLayoutsAsFileInBackground(long, String, long, boolean,
970             *             long[], Map, Date, Date)}
971             */
972            @Deprecated
973            @Override
974            public long exportLayoutsAsFileInBackground(
975                            long userId, String taskName, long groupId, boolean privateLayout,
976                            long[] layoutIds, Map<String, String[]> parameterMap,
977                            Date startDate, Date endDate, String fileName)
978                    throws PortalException {
979    
980                    return exportLayoutsAsFileInBackground(
981                            userId, taskName, groupId, privateLayout, layoutIds, parameterMap,
982                            startDate, endDate);
983            }
984    
985            /**
986             * Exports the portlet information (categories, permissions, ... etc.) as a
987             * byte array.
988             *
989             * @param  plid the primary key of the layout
990             * @param  groupId the primary key of the group
991             * @param  portletId the primary key of the portlet
992             * @param  parameterMap the mapping of parameters indicating which
993             *         information to export. For information on the keys used in the
994             *         map see {@link
995             *         com.liferay.portal.kernel.lar.PortletDataHandlerKeys}.
996             * @param  startDate the export's start date
997             * @param  endDate the export's end date
998             * @return the portlet information as a byte array
999             * @throws PortalException if a group or portlet with the primary key could
1000             *         not be found, or if some other portal exception occurred
1001             */
1002            @Override
1003            public byte[] exportPortletInfo(
1004                            long plid, long groupId, String portletId,
1005                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
1006                    throws PortalException {
1007    
1008                    File file = exportPortletInfoAsFile(
1009                            plid, groupId, portletId, parameterMap, startDate, endDate);
1010    
1011                    try {
1012                            return FileUtil.getBytes(file);
1013                    }
1014                    catch (IOException ioe) {
1015                            throw new SystemException(ioe);
1016                    }
1017                    finally {
1018                            file.delete();
1019                    }
1020            }
1021    
1022            @Override
1023            public byte[] exportPortletInfo(
1024                            long companyId, String portletId,
1025                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
1026                    throws PortalException {
1027    
1028                    File file = exportPortletInfoAsFile(
1029                            companyId, portletId, parameterMap, startDate, endDate);
1030    
1031                    try {
1032                            return FileUtil.getBytes(file);
1033                    }
1034                    catch (IOException ioe) {
1035                            throw new SystemException(ioe);
1036                    }
1037                    finally {
1038                            file.delete();
1039                    }
1040            }
1041    
1042            /**
1043             * Exports the portlet information (categories, permissions, ... etc.) as a
1044             * file.
1045             *
1046             * @param  plid the primary key of the layout
1047             * @param  groupId the primary key of the group
1048             * @param  portletId the primary key of the portlet
1049             * @param  parameterMap the mapping of parameters indicating which
1050             *         information to export. For information on the keys used in the
1051             *         map see {@link
1052             *         com.liferay.portal.kernel.lar.PortletDataHandlerKeys}.
1053             * @param  startDate the export's start date
1054             * @param  endDate the export's end date
1055             * @return the portlet information as a file
1056             * @throws PortalException if a group or portlet with the primary key could
1057             *         not be found, or if some other portal exception occurred
1058             */
1059            @Override
1060            public File exportPortletInfoAsFile(
1061                            long plid, long groupId, String portletId,
1062                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
1063                    throws PortalException {
1064    
1065                    try {
1066                            PortletExporter portletExporter = PortletExporter.getInstance();
1067    
1068                            return portletExporter.exportPortletInfoAsFile(
1069                                    plid, groupId, portletId, parameterMap, startDate, endDate);
1070                    }
1071                    catch (PortalException pe) {
1072                            throw pe;
1073                    }
1074                    catch (SystemException se) {
1075                            throw se;
1076                    }
1077                    catch (Exception e) {
1078                            throw new SystemException(e);
1079                    }
1080            }
1081    
1082            @Override
1083            public File exportPortletInfoAsFile(
1084                            long companyId, String portletId,
1085                            Map<String, String[]> parameterMap, Date startDate, Date endDate)
1086                    throws PortalException {
1087    
1088                    Group companyGroup = groupLocalService.getCompanyGroup(companyId);
1089                    Group controlPanelGroup = groupPersistence.findByC_F(
1090                            companyId, GroupConstants.CONTROL_PANEL_FRIENDLY_URL);
1091    
1092                    Layout controlPanelLayout = layoutPersistence.findByG_P_T_First(
1093                            controlPanelGroup.getGroupId(), true,
1094                            LayoutConstants.TYPE_CONTROL_PANEL, null);
1095    
1096                    return exportPortletInfoAsFile(
1097                            controlPanelLayout.getPlid(), companyGroup.getGroupId(), portletId,
1098                            parameterMap, startDate, endDate);
1099            }
1100    
1101            @Override
1102            public long exportPortletInfoAsFileInBackground(
1103                            long userId, String taskName, long plid, long groupId,
1104                            String portletId, Map<String, String[]> parameterMap,
1105                            Date startDate, Date endDate, String fileName)
1106                    throws PortalException {
1107    
1108                    Map<String, Serializable> taskContextMap =
1109                            BackgroundTaskContextMapFactory.buildTaskContextMap(
1110                                    userId, plid, groupId, portletId, parameterMap,
1111                                    Constants.EXPORT, startDate, endDate, fileName);
1112    
1113                    BackgroundTask backgroundTask =
1114                            backgroundTaskLocalService.addBackgroundTask(
1115                                    userId, groupId, taskName, null,
1116                                    PortletExportBackgroundTaskExecutor.class, taskContextMap,
1117                                    new ServiceContext());
1118    
1119                    return backgroundTask.getBackgroundTaskId();
1120            }
1121    
1122            @Override
1123            public long exportPortletInfoAsFileInBackground(
1124                            long userId, String taskName, String portletId,
1125                            Map<String, String[]> parameterMap, Date startDate, Date endDate,
1126                            String fileName)
1127                    throws PortalException {
1128    
1129                    User user = userPersistence.findByPrimaryKey(userId);
1130    
1131                    Group companyGroup = groupLocalService.getCompanyGroup(
1132                            user.getCompanyId());
1133                    Group controlPanelGroup = groupPersistence.findByC_F(
1134                            user.getCompanyId(), GroupConstants.CONTROL_PANEL_FRIENDLY_URL);
1135    
1136                    Layout controlPanelLayout = layoutPersistence.findByG_P_T_First(
1137                            controlPanelGroup.getGroupId(), true,
1138                            LayoutConstants.TYPE_CONTROL_PANEL, null);
1139    
1140                    return exportPortletInfoAsFileInBackground(
1141                            userId, taskName, controlPanelLayout.getPlid(),
1142                            companyGroup.getGroupId(), portletId, parameterMap, startDate,
1143                            endDate, fileName);
1144            }
1145    
1146            @Override
1147            public Layout fetchFirstLayout(
1148                    long groupId, boolean privateLayout, long parentLayoutId) {
1149    
1150                    return layoutPersistence.fetchByG_P_P_First(
1151                            groupId, privateLayout, parentLayoutId,
1152                            new LayoutPriorityComparator());
1153            }
1154    
1155            @Override
1156            public Layout fetchLayout(
1157                    long groupId, boolean privateLayout, long layoutId) {
1158    
1159                    return layoutPersistence.fetchByG_P_L(groupId, privateLayout, layoutId);
1160            }
1161    
1162            @Override
1163            public Layout fetchLayoutByFriendlyURL(
1164                    long groupId, boolean privateLayout, String friendlyURL) {
1165    
1166                    return layoutPersistence.fetchByG_P_F(
1167                            groupId, privateLayout, friendlyURL);
1168            }
1169    
1170            /**
1171             * Returns the primary key of the default layout for the group
1172             *
1173             * @param  groupId the primary key of the group
1174             * @return the primary key of the default layout for the group (optionally
1175             *         {@link com.liferay.portal.model.LayoutConstants#DEFAULT_PLID})
1176             */
1177            @Override
1178            public long getDefaultPlid(long groupId) {
1179                    if (groupId > 0) {
1180                            List<Layout> layouts = layoutPersistence.findByGroupId(
1181                                    groupId, 0, 1);
1182    
1183                            if (!layouts.isEmpty()) {
1184                                    Layout layout = layouts.get(0);
1185    
1186                                    return layout.getPlid();
1187                            }
1188                    }
1189    
1190                    return LayoutConstants.DEFAULT_PLID;
1191            }
1192    
1193            /**
1194             * Returns primary key of the matching default layout for the group
1195             *
1196             * @param  groupId the primary key of the group
1197             * @param  privateLayout whether the layout is private to the group
1198             * @return the primary key of the default layout for the group; {@link
1199             *         com.liferay.portal.model.LayoutConstants#DEFAULT_PLID}) otherwise
1200             */
1201            @Override
1202            public long getDefaultPlid(long groupId, boolean privateLayout) {
1203                    if (groupId > 0) {
1204                            List<Layout> layouts = layoutPersistence.findByG_P(
1205                                    groupId, privateLayout, 0, 1);
1206    
1207                            if (!layouts.isEmpty()) {
1208                                    Layout layout = layouts.get(0);
1209    
1210                                    return layout.getPlid();
1211                            }
1212                    }
1213    
1214                    return LayoutConstants.DEFAULT_PLID;
1215            }
1216    
1217            /**
1218             * Returns primary key of the default portlet layout for the group
1219             *
1220             * @param  groupId the primary key of the group
1221             * @param  privateLayout whether the layout is private to the group
1222             * @param  portletId the primary key of the portlet
1223             * @return the primary key of the default portlet layout for the group;
1224             *         {@link com.liferay.portal.model.LayoutConstants#DEFAULT_PLID}
1225             *         otherwise
1226             * @throws PortalException if a portlet with the primary key could not be
1227             *         found
1228             */
1229            @Override
1230            public long getDefaultPlid(
1231                            long groupId, boolean privateLayout, String portletId)
1232                    throws PortalException {
1233    
1234                    if (groupId > 0) {
1235                            List<Layout> layouts = layoutPersistence.findByG_P(
1236                                    groupId, privateLayout);
1237    
1238                            for (Layout layout : layouts) {
1239                                    if (layout.isTypePortlet()) {
1240                                            LayoutTypePortlet layoutTypePortlet =
1241                                                    (LayoutTypePortlet)layout.getLayoutType();
1242    
1243                                            if (layoutTypePortlet.hasPortletId(portletId)) {
1244                                                    return layout.getPlid();
1245                                            }
1246                                    }
1247                            }
1248                    }
1249    
1250                    return LayoutConstants.DEFAULT_PLID;
1251            }
1252    
1253            /**
1254             * Returns the layout for the friendly URL
1255             *
1256             * @param  groupId the primary key of the group
1257             * @param  privateLayout whether the layout is private to the group
1258             * @param  friendlyURL the friendly URL of the layout
1259             * @return the layout for the friendly URL
1260             * @throws PortalException if the friendly URL is <code>null</code> or a
1261             *         matching layout could not be found
1262             */
1263            @Override
1264            public Layout getFriendlyURLLayout(
1265                            long groupId, boolean privateLayout, String friendlyURL)
1266                    throws PortalException {
1267    
1268                    if (Validator.isNull(friendlyURL)) {
1269                            StringBundler sb = new StringBundler(5);
1270    
1271                            sb.append("{groupId=");
1272                            sb.append(groupId);
1273                            sb.append(", privateLayout=");
1274                            sb.append(privateLayout);
1275                            sb.append("}");
1276    
1277                            throw new NoSuchLayoutException(sb.toString());
1278                    }
1279    
1280                    friendlyURL = layoutLocalServiceHelper.getFriendlyURL(friendlyURL);
1281    
1282                    Layout layout = null;
1283    
1284                    List<LayoutFriendlyURL> layoutFriendlyURLs =
1285                            layoutFriendlyURLPersistence.findByG_P_F(
1286                                    groupId, privateLayout, friendlyURL, 0, 1);
1287    
1288                    if (!layoutFriendlyURLs.isEmpty()) {
1289                            LayoutFriendlyURL layoutFriendlyURL = layoutFriendlyURLs.get(0);
1290    
1291                            layout = layoutPersistence.findByPrimaryKey(
1292                                    layoutFriendlyURL.getPlid());
1293                    }
1294    
1295                    if ((layout == null) &&
1296                            friendlyURL.startsWith(StringPool.SLASH) &&
1297                            Validator.isNumber(friendlyURL.substring(1))) {
1298    
1299                            long layoutId = GetterUtil.getLong(friendlyURL.substring(1));
1300    
1301                            layout = layoutPersistence.fetchByG_P_L(
1302                                    groupId, privateLayout, layoutId);
1303                    }
1304    
1305                    if (layout == null) {
1306                            StringBundler sb = new StringBundler(7);
1307    
1308                            sb.append("{groupId=");
1309                            sb.append(groupId);
1310                            sb.append(", privateLayout=");
1311                            sb.append(privateLayout);
1312                            sb.append(", friendlyURL=");
1313                            sb.append(friendlyURL);
1314                            sb.append("}");
1315    
1316                            throw new NoSuchLayoutException(sb.toString());
1317                    }
1318    
1319                    return layout;
1320            }
1321    
1322            /**
1323             * Returns the layout matching the primary key, group, and privacy; throws a
1324             * {@link com.liferay.portal.NoSuchLayoutException} otherwise.
1325             *
1326             * @param  groupId the primary key of the group
1327             * @param  privateLayout whether the layout is private to the group
1328             * @param  layoutId the primary key of the layout
1329             * @return the matching layout
1330             * @throws PortalException if a matching layout could not be found
1331             */
1332            @Override
1333            public Layout getLayout(long groupId, boolean privateLayout, long layoutId)
1334                    throws PortalException {
1335    
1336                    return layoutPersistence.findByG_P_L(groupId, privateLayout, layoutId);
1337            }
1338    
1339            /**
1340             * Returns the layout for the icon image; throws a {@link
1341             * com.liferay.portal.NoSuchLayoutException} otherwise.
1342             *
1343             * @param  iconImageId the primary key of the icon image
1344             * @return Returns the layout for the icon image
1345             * @throws PortalException if an icon image with the primary key could not
1346             *         be found
1347             */
1348            @Override
1349            public Layout getLayoutByIconImageId(long iconImageId)
1350                    throws PortalException {
1351    
1352                    return layoutPersistence.findByIconImageId(iconImageId);
1353            }
1354    
1355            /**
1356             * Returns all the layouts belonging to the group.
1357             *
1358             * @param  groupId the primary key of the group
1359             * @param  privateLayout whether the layout is private to the group
1360             * @return the matching layouts, or <code>null</code> if no matches were
1361             *         found
1362             */
1363            @Override
1364            public List<Layout> getLayouts(long groupId, boolean privateLayout) {
1365                    return layoutPersistence.findByG_P(groupId, privateLayout);
1366            }
1367    
1368            /**
1369             * Returns all the layouts belonging to the group that are children of the
1370             * parent layout.
1371             *
1372             * @param  groupId the primary key of the group
1373             * @param  privateLayout whether the layout is private to the group
1374             * @param  parentLayoutId the primary key of the parent layout
1375             * @return the matching layouts, or <code>null</code> if no matches were
1376             *         found
1377             */
1378            @Override
1379            public List<Layout> getLayouts(
1380                    long groupId, boolean privateLayout, long parentLayoutId) {
1381    
1382                    return layoutPersistence.findByG_P_P(
1383                            groupId, privateLayout, parentLayoutId);
1384            }
1385    
1386            /**
1387             * Returns a range of all the layouts belonging to the group that are
1388             * children of the parent layout.
1389             *
1390             * <p>
1391             * Useful when paginating results. Returns a maximum of <code>end -
1392             * start</code> instances. <code>start</code> and <code>end</code> are not
1393             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1394             * refers to the first result in the set. Setting both <code>start</code>
1395             * and <code>end</code> to {@link
1396             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1397             * result set.
1398             * </p>
1399             *
1400             * @param  groupId the primary key of the group
1401             * @param  privateLayout whether the layout is private to the group
1402             * @param  parentLayoutId the primary key of the parent layout
1403             * @param  incomplete whether the layout is incomplete
1404             * @param  start the lower bound of the range of layouts
1405             * @param  end the upper bound of the range of layouts (not inclusive)
1406             * @return the matching layouts, or <code>null</code> if no matches were
1407             *         found
1408             */
1409            @Override
1410            public List<Layout> getLayouts(
1411                    long groupId, boolean privateLayout, long parentLayoutId,
1412                    boolean incomplete, int start, int end) {
1413    
1414                    return layoutPersistence.findByG_P_P(
1415                            groupId, privateLayout, parentLayoutId, start, end);
1416            }
1417    
1418            /**
1419             * Returns all the layouts that match the layout IDs and belong to the
1420             * group.
1421             *
1422             * @param  groupId the primary key of the group
1423             * @param  privateLayout whether the layout is private to the group
1424             * @param  layoutIds the primary keys of the layouts
1425             * @return the matching layouts, or an empty list if no matches were found
1426             * @throws PortalException if a group or layout with the primary key could
1427             *         not be found
1428             */
1429            @Override
1430            public List<Layout> getLayouts(
1431                            long groupId, boolean privateLayout, long[] layoutIds)
1432                    throws PortalException {
1433    
1434                    List<Layout> layouts = new ArrayList<Layout>();
1435    
1436                    for (long layoutId : layoutIds) {
1437                            Layout layout = getLayout(groupId, privateLayout, layoutId);
1438    
1439                            layouts.add(layout);
1440                    }
1441    
1442                    return layouts;
1443            }
1444    
1445            /**
1446             * Returns all the layouts that match the type and belong to the group.
1447             *
1448             * @param  groupId the primary key of the group
1449             * @param  privateLayout whether the layout is private to the group
1450             * @param  type the type of the layouts (optionally {@link
1451             *         com.liferay.portal.model.LayoutConstants#TYPE_PORTLET})
1452             * @return the matching layouts, or <code>null</code> if no matches were
1453             *         found
1454             */
1455            @Override
1456            public List<Layout> getLayouts(
1457                    long groupId, boolean privateLayout, String type) {
1458    
1459                    return layoutPersistence.findByG_P_T(groupId, privateLayout, type);
1460            }
1461    
1462            /**
1463             * Returns the layout references for all the layouts that belong to the
1464             * company and belong to the portlet that matches the preferences.
1465             *
1466             * @param  companyId the primary key of the company
1467             * @param  portletId the primary key of the portlet
1468             * @param  preferencesKey the portlet's preference key
1469             * @param  preferencesValue the portlet's preference value
1470             * @return the layout references of the matching layouts
1471             */
1472            @Override
1473            public LayoutReference[] getLayouts(
1474                    long companyId, String portletId, String preferencesKey,
1475                    String preferencesValue) {
1476    
1477                    List<LayoutReference> layoutReferences = layoutFinder.findByC_P_P(
1478                            companyId, portletId, preferencesKey, preferencesValue);
1479    
1480                    return layoutReferences.toArray(
1481                            new LayoutReference[layoutReferences.size()]);
1482            }
1483    
1484            @Override
1485            public List<Layout> getLayoutsByLayoutPrototypeUuid(
1486                    String layoutPrototypeUuid) {
1487    
1488                    return layoutPersistence.findByLayoutPrototypeUuid(layoutPrototypeUuid);
1489            }
1490    
1491            @Override
1492            public int getLayoutsByLayoutPrototypeUuidCount(
1493                    String layoutPrototypeUuid) {
1494    
1495                    return layoutPersistence.countByLayoutPrototypeUuid(
1496                            layoutPrototypeUuid);
1497            }
1498    
1499            @Override
1500            public int getLayoutsCount(Group group, boolean privateLayout)
1501                    throws PortalException {
1502    
1503                    return getLayoutsCount(group, privateLayout, true);
1504            }
1505    
1506            @Override
1507            public int getLayoutsCount(
1508                            Group group, boolean privateLayout, boolean includeUserGroups)
1509                    throws PortalException {
1510    
1511                    LayoutSet layoutSet = layoutSetPersistence.findByG_P(
1512                            group.getGroupId(), privateLayout);
1513    
1514                    int count = layoutSet.getPageCount();
1515    
1516                    if (!group.isUser() || !includeUserGroups) {
1517                            return count;
1518                    }
1519    
1520                    long[] userGroupIds = userPersistence.getUserGroupPrimaryKeys(
1521                            group.getClassPK());
1522    
1523                    if (userGroupIds.length != 0) {
1524                            long userGroupClassNameId = classNameLocalService.getClassNameId(
1525                                    UserGroup.class);
1526    
1527                            for (long userGroupId : userGroupIds) {
1528                                    Group userGroupGroup = groupPersistence.findByC_C_C(
1529                                            group.getCompanyId(), userGroupClassNameId, userGroupId);
1530    
1531                                    layoutSet = layoutSetPersistence.findByG_P(
1532                                            userGroupGroup.getGroupId(), privateLayout);
1533    
1534                                    count += layoutSet.getPageCount();
1535                            }
1536                    }
1537    
1538                    return count;
1539            }
1540    
1541            @Override
1542            public int getLayoutsCount(
1543                    Group group, boolean privateLayout, long parentLayoutId) {
1544    
1545                    return layoutPersistence.countByG_P_P(
1546                            group.getGroupId(), privateLayout, parentLayoutId);
1547            }
1548    
1549            @Override
1550            public int getLayoutsCount(User user, boolean privateLayout)
1551                    throws PortalException {
1552    
1553                    return getLayoutsCount(user, privateLayout, true);
1554            }
1555    
1556            @Override
1557            public int getLayoutsCount(
1558                            User user, boolean privateLayout, boolean includeUserGroups)
1559                    throws PortalException {
1560    
1561                    long classNameId = classNameLocalService.getClassNameId(User.class);
1562    
1563                    Group group = groupPersistence.findByC_C_C(
1564                            user.getCompanyId(), classNameId, user.getUserId());
1565    
1566                    return getLayoutsCount(group, privateLayout, includeUserGroups);
1567            }
1568    
1569            /**
1570             * Returns the primary key to use for the next layout.
1571             *
1572             * @param  groupId the primary key of the group
1573             * @param  privateLayout whether the layout is private to the group
1574             * @return the primary key to use for the next layout
1575             */
1576            @Override
1577            public long getNextLayoutId(long groupId, boolean privateLayout) {
1578                    long nextLayoutId = counterLocalService.increment(
1579                            getCounterName(groupId, privateLayout));
1580    
1581                    if (nextLayoutId == 1) {
1582                            List<Layout> layouts = layoutPersistence.findByG_P(
1583                                    groupId, privateLayout, 0, 1, new LayoutComparator());
1584    
1585                            if (!layouts.isEmpty()) {
1586                                    Layout layout = layouts.get(0);
1587    
1588                                    nextLayoutId = layout.getLayoutId() + 1;
1589    
1590                                    counterLocalService.reset(
1591                                            getCounterName(groupId, privateLayout), nextLayoutId);
1592                            }
1593                    }
1594    
1595                    return nextLayoutId;
1596            }
1597    
1598            /**
1599             * Returns all the layouts without resource permissions
1600             *
1601             * @param  roleId the primary key of the role
1602             * @return all the layouts without resource permissions
1603             */
1604            @Override
1605            public List<Layout> getNoPermissionLayouts(long roleId) {
1606                    return layoutFinder.findByNoPermissions(roleId);
1607            }
1608    
1609            /**
1610             * Returns all the layouts whose friendly URLs are <code>null</code>
1611             *
1612             * @return all the layouts whose friendly URLs are <code>null</code>
1613             */
1614            @Override
1615            public List<Layout> getNullFriendlyURLLayouts() {
1616                    return layoutFinder.findByNullFriendlyURL();
1617            }
1618    
1619            @Override
1620            public Layout getParentLayout(Layout layout) throws PortalException {
1621                    Layout parentLayout = null;
1622    
1623                    if (layout instanceof VirtualLayout) {
1624                            VirtualLayout virtualLayout = (VirtualLayout)layout;
1625    
1626                            Layout sourceLayout = virtualLayout.getSourceLayout();
1627    
1628                            parentLayout = getLayout(
1629                                    sourceLayout.getGroupId(), sourceLayout.isPrivateLayout(),
1630                                    sourceLayout.getParentLayoutId());
1631    
1632                            parentLayout = new VirtualLayout(parentLayout, layout.getGroup());
1633                    }
1634                    else {
1635                            parentLayout = getLayout(
1636                                    layout.getGroupId(), layout.isPrivateLayout(),
1637                                    layout.getParentLayoutId());
1638                    }
1639    
1640                    return parentLayout;
1641            }
1642    
1643            /**
1644             * Returns all the layouts within scope of the group
1645             *
1646             * @param  groupId the primary key of the group
1647             * @param  privateLayout whether the layout is private to the group
1648             * @return the layouts within scope of the group
1649             */
1650            @Override
1651            public List<Layout> getScopeGroupLayouts(
1652                    long groupId, boolean privateLayout) {
1653    
1654                    return layoutFinder.findByScopeGroup(groupId, privateLayout);
1655            }
1656    
1657            @Override
1658            public boolean hasLayouts(Group group, boolean privateLayout)
1659                    throws PortalException {
1660    
1661                    return hasLayouts(group, privateLayout, true);
1662            }
1663    
1664            @Override
1665            public boolean hasLayouts(
1666                            Group group, boolean privateLayout, boolean includeUserGroups)
1667                    throws PortalException {
1668    
1669                    LayoutSet layoutSet = layoutSetPersistence.findByG_P(
1670                            group.getGroupId(), privateLayout);
1671    
1672                    if (layoutSet.getPageCount() > 0) {
1673                            return true;
1674                    }
1675    
1676                    if (!group.isUser() || !includeUserGroups) {
1677                            return false;
1678                    }
1679    
1680                    long[] userGroupIds = userPersistence.getUserGroupPrimaryKeys(
1681                            group.getClassPK());
1682    
1683                    if (userGroupIds.length != 0) {
1684                            long userGroupClassNameId = classNameLocalService.getClassNameId(
1685                                    UserGroup.class);
1686    
1687                            for (long userGroupId : userGroupIds) {
1688                                    Group userGroupGroup = groupPersistence.findByC_C_C(
1689                                            group.getCompanyId(), userGroupClassNameId, userGroupId);
1690    
1691                                    layoutSet = layoutSetPersistence.findByG_P(
1692                                            userGroupGroup.getGroupId(), privateLayout);
1693    
1694                                    if (layoutSet.getPageCount() > 0) {
1695                                            return true;
1696                                    }
1697                            }
1698                    }
1699    
1700                    return false;
1701            }
1702    
1703            /**
1704             * Returns <code>true</code> if the group has any layouts;
1705             * <code>false</code> otherwise.
1706             *
1707             * @param  groupId the primary key of the group
1708             * @param  privateLayout whether the layout is private to the group
1709             * @param  parentLayoutId the primary key of the parent layout
1710             * @return <code>true</code> if the group has any layouts;
1711             *         <code>false</code> otherwise
1712             */
1713            @Override
1714            public boolean hasLayouts(
1715                    long groupId, boolean privateLayout, long parentLayoutId) {
1716    
1717                    return layoutPersistence.countByG_P_P(
1718                            groupId, privateLayout, parentLayoutId) > 0;
1719            }
1720    
1721            @Override
1722            public boolean hasLayouts(User user, boolean privateLayout)
1723                    throws PortalException {
1724    
1725                    return hasLayouts(user, privateLayout, true);
1726            }
1727    
1728            @Override
1729            public boolean hasLayouts(
1730                            User user, boolean privateLayout, boolean includeUserGroups)
1731                    throws PortalException {
1732    
1733                    long classNameId = classNameLocalService.getClassNameId(User.class);
1734    
1735                    Group group = groupPersistence.findByC_C_C(
1736                            user.getCompanyId(), classNameId, user.getUserId());
1737    
1738                    return hasLayouts(group, privateLayout, includeUserGroups);
1739            }
1740    
1741            @Override
1742            public boolean hasLayoutSetPrototypeLayout(
1743                            long layoutSetPrototypeId, String layoutUuid)
1744                    throws PortalException {
1745    
1746                    LayoutSetPrototype layoutSetPrototype =
1747                            layoutSetPrototypeLocalService.getLayoutSetPrototype(
1748                                    layoutSetPrototypeId);
1749    
1750                    return layoutLocalServiceHelper.hasLayoutSetPrototypeLayout(
1751                            layoutSetPrototype, layoutUuid);
1752            }
1753    
1754            @Override
1755            public boolean hasLayoutSetPrototypeLayout(
1756                            String layoutSetPrototypeUuid, long companyId, String layoutUuid)
1757                    throws PortalException {
1758    
1759                    LayoutSetPrototype layoutSetPrototype =
1760                            layoutSetPrototypeLocalService.
1761                                    getLayoutSetPrototypeByUuidAndCompanyId(
1762                                            layoutSetPrototypeUuid, companyId);
1763    
1764                    return layoutLocalServiceHelper.hasLayoutSetPrototypeLayout(
1765                            layoutSetPrototype, layoutUuid);
1766            }
1767    
1768            /**
1769             * Imports the layouts from the byte array.
1770             *
1771             * @param  userId the primary key of the user
1772             * @param  groupId the primary key of the group
1773             * @param  privateLayout whether the layout is private to the group
1774             * @param  parameterMap the mapping of parameters indicating which
1775             *         information will be imported. For information on the keys used in
1776             *         the map see {@link
1777             *         com.liferay.portal.kernel.lar.PortletDataHandlerKeys}.
1778             * @param  bytes the byte array with the data
1779             * @throws PortalException if a group or user with the primary key could not
1780             *         be found, or if some other portal exception occurred
1781             * @see    com.liferay.portal.lar.LayoutImporter
1782             */
1783            @Override
1784            public void importLayouts(
1785                            long userId, long groupId, boolean privateLayout,
1786                            Map<String, String[]> parameterMap, byte[] bytes)
1787                    throws PortalException {
1788    
1789                    importLayouts(
1790                            userId, groupId, privateLayout, parameterMap,
1791                            new UnsyncByteArrayInputStream(bytes));
1792            }
1793    
1794            /**
1795             * Imports the layouts from the file.
1796             *
1797             * @param  userId the primary key of the user
1798             * @param  groupId the primary key of the group
1799             * @param  privateLayout whether the layout is private to the group
1800             * @param  parameterMap the mapping of parameters indicating which
1801             *         information will be imported. For information on the keys used in
1802             *         the map see {@link
1803             *         com.liferay.portal.kernel.lar.PortletDataHandlerKeys}.
1804             * @param  file the LAR file with the data
1805             * @throws PortalException if a group or user with the primary key could not
1806             *         be found, or if some other portal exception occurred
1807             * @see    com.liferay.portal.lar.LayoutImporter
1808             */
1809            @Override
1810            public void importLayouts(
1811                            long userId, long groupId, boolean privateLayout,
1812                            Map<String, String[]> parameterMap, File file)
1813                    throws PortalException {
1814    
1815                    try {
1816                            LayoutImporter layoutImporter = LayoutImporter.getInstance();
1817    
1818                            layoutImporter.importLayouts(
1819                                    userId, groupId, privateLayout, parameterMap, file);
1820                    }
1821                    catch (PortalException pe) {
1822                            Throwable cause = pe.getCause();
1823    
1824                            if (cause instanceof LocaleException) {
1825                                    throw (PortalException)cause;
1826                            }
1827    
1828                            throw pe;
1829                    }
1830                    catch (SystemException se) {
1831                            throw se;
1832                    }
1833                    catch (Exception e) {
1834                            throw new SystemException(e);
1835                    }
1836            }
1837    
1838            /**
1839             * Imports the layouts from the input stream.
1840             *
1841             * @param  userId the primary key of the user
1842             * @param  groupId the primary key of the group
1843             * @param  privateLayout whether the layout is private to the group
1844             * @param  parameterMap the mapping of parameters indicating which
1845             *         information will be imported. For information on the keys used in
1846             *         the map see {@link
1847             *         com.liferay.portal.kernel.lar.PortletDataHandlerKeys}.
1848             * @param  is the input stream
1849             * @throws PortalException if a group or user with the primary key could not
1850             *         be found, or if some other portal exception occurred
1851             * @see    com.liferay.portal.lar.LayoutImporter
1852             */
1853            @Override
1854            public void importLayouts(
1855                            long userId, long groupId, boolean privateLayout,
1856                            Map<String, String[]> parameterMap, InputStream is)
1857                    throws PortalException {
1858    
1859                    File file = null;
1860    
1861                    try {
1862                            file = FileUtil.createTempFile("lar");
1863    
1864                            FileUtil.write(file, is);
1865    
1866                            importLayouts(userId, groupId, privateLayout, parameterMap, file);
1867                    }
1868                    catch (IOException ioe) {
1869                            throw new SystemException(ioe);
1870                    }
1871                    finally {
1872                            FileUtil.delete(file);
1873                    }
1874            }
1875    
1876            @Override
1877            public long importLayoutsInBackground(
1878                            long userId, String taskName, long groupId, boolean privateLayout,
1879                            Map<String, String[]> parameterMap, File file)
1880                    throws PortalException {
1881    
1882                    Map<String, Serializable> taskContextMap =
1883                            BackgroundTaskContextMapFactory.buildTaskContextMap(
1884                                    userId, groupId, privateLayout, null, parameterMap,
1885                                    Constants.IMPORT, null, null, file.getName());
1886    
1887                    BackgroundTask backgroundTask =
1888                            backgroundTaskLocalService.addBackgroundTask(
1889                                    userId, groupId, taskName, null,
1890                                    LayoutImportBackgroundTaskExecutor.class, taskContextMap,
1891                                    new ServiceContext());
1892    
1893                    backgroundTaskLocalService.addBackgroundTaskAttachment(
1894                            userId, backgroundTask.getBackgroundTaskId(), file.getName(), file);
1895    
1896                    return backgroundTask.getBackgroundTaskId();
1897            }
1898    
1899            @Override
1900            public long importLayoutsInBackground(
1901                            long userId, String taskName, long groupId, boolean privateLayout,
1902                            Map<String, String[]> parameterMap, InputStream is)
1903                    throws PortalException {
1904    
1905                    File file = null;
1906    
1907                    try {
1908                            file = FileUtil.createTempFile("lar");
1909    
1910                            FileUtil.write(file, is);
1911    
1912                            return importLayoutsInBackground(
1913                                    userId, taskName, groupId, privateLayout, parameterMap, file);
1914                    }
1915                    catch (IOException ioe) {
1916                            throw new SystemException(ioe);
1917                    }
1918                    finally {
1919                            FileUtil.delete(file);
1920                    }
1921            }
1922    
1923            /**
1924             * Imports the portlet information (categories, permissions, ... etc.) from
1925             * the file.
1926             *
1927             * @param  userId the primary key of the user
1928             * @param  plid the primary key of the target layout
1929             * @param  groupId the primary key of the target group
1930             * @param  portletId the primary key of the portlet
1931             * @param  parameterMap the mapping of parameters indicating which
1932             *         information will be imported. For information on the keys used in
1933             *         the map see {@link
1934             *         com.liferay.portal.kernel.lar.PortletDataHandlerKeys}.
1935             * @param  file the LAR file with the data
1936             * @throws PortalException if a group, layout, portlet or user with the
1937             *         primary key could not be found
1938             */
1939            @Override
1940            public void importPortletInfo(
1941                            long userId, long plid, long groupId, String portletId,
1942                            Map<String, String[]> parameterMap, File file)
1943                    throws PortalException {
1944    
1945                    try {
1946                            PortletImporter portletImporter = PortletImporter.getInstance();
1947    
1948                            portletImporter.importPortletInfo(
1949                                    userId, plid, groupId, portletId, parameterMap, file);
1950                    }
1951                    catch (PortalException pe) {
1952                            Throwable cause = pe.getCause();
1953    
1954                            while (true) {
1955                                    if (cause == null) {
1956                                            break;
1957                                    }
1958    
1959                                    if ((cause instanceof LocaleException) ||
1960                                            (cause instanceof
1961                                                    RecordSetDuplicateRecordSetKeyException) ||
1962                                            (cause instanceof
1963                                                    StructureDuplicateStructureKeyException)) {
1964    
1965                                            throw (PortalException)cause;
1966                                    }
1967    
1968                                    if (cause instanceof PortletDataException) {
1969                                            cause = cause.getCause();
1970                                    }
1971                                    else {
1972                                            break;
1973                                    }
1974                            }
1975    
1976                            throw pe;
1977                    }
1978                    catch (SystemException se) {
1979                            throw se;
1980                    }
1981                    catch (Exception e) {
1982                            throw new SystemException(e);
1983                    }
1984            }
1985    
1986            /**
1987             * Imports the portlet information (categories, permissions, ... etc.) from
1988             * the input stream.
1989             *
1990             * @param  userId the primary key of the user
1991             * @param  plid the primary key of the layout
1992             * @param  groupId the primary key of the group
1993             * @param  portletId the primary key of the portlet
1994             * @param  parameterMap the mapping of parameters indicating which
1995             *         information will be imported. For information on the keys used in
1996             *         the map see {@link
1997             *         com.liferay.portal.kernel.lar.PortletDataHandlerKeys}.
1998             * @param  is the input stream
1999             * @throws PortalException if a group, portlet, layout or user with the
2000             *         primary key could not be found
2001             */
2002            @Override
2003            public void importPortletInfo(
2004                            long userId, long plid, long groupId, String portletId,
2005                            Map<String, String[]> parameterMap, InputStream is)
2006                    throws PortalException {
2007    
2008                    File file = null;
2009    
2010                    try {
2011                            file = FileUtil.createTempFile("lar");
2012    
2013                            FileUtil.write(file, is);
2014    
2015                            importPortletInfo(
2016                                    userId, plid, groupId, portletId, parameterMap, file);
2017                    }
2018                    catch (IOException ioe) {
2019                            throw new SystemException(ioe);
2020                    }
2021                    finally {
2022                            FileUtil.delete(file);
2023                    }
2024            }
2025    
2026            @Override
2027            public void importPortletInfo(
2028                            long userId, String portletId, Map<String, String[]> parameterMap,
2029                            File file)
2030                    throws PortalException {
2031    
2032                    User user = userPersistence.findByPrimaryKey(userId);
2033    
2034                    Group companyGroup = groupLocalService.getCompanyGroup(
2035                            user.getCompanyId());
2036    
2037                    Group controlPanelGroup = groupPersistence.findByC_F(
2038                            user.getCompanyId(), GroupConstants.CONTROL_PANEL_FRIENDLY_URL);
2039    
2040                    Layout controlPanelLayout = layoutPersistence.findByG_P_T_First(
2041                            controlPanelGroup.getGroupId(), true,
2042                            LayoutConstants.TYPE_CONTROL_PANEL, null);
2043    
2044                    importPortletInfo(
2045                            userId, controlPanelLayout.getPlid(), companyGroup.getGroupId(),
2046                            portletId, parameterMap, file);
2047            }
2048    
2049            @Override
2050            public void importPortletInfo(
2051                            long userId, String portletId, Map<String, String[]> parameterMap,
2052                            InputStream is)
2053                    throws PortalException {
2054    
2055                    File file = null;
2056    
2057                    try {
2058                            file = FileUtil.createTempFile("lar");
2059    
2060                            FileUtil.write(file, is);
2061    
2062                            importPortletInfo(userId, portletId, parameterMap, file);
2063                    }
2064                    catch (IOException ioe) {
2065                            throw new SystemException(ioe);
2066                    }
2067                    finally {
2068                            FileUtil.delete(file);
2069                    }
2070            }
2071    
2072            @Override
2073            public long importPortletInfoInBackground(
2074                            long userId, String taskName, long plid, long groupId,
2075                            String portletId, Map<String, String[]> parameterMap, File file)
2076                    throws PortalException {
2077    
2078                    Map<String, Serializable> taskContextMap =
2079                            BackgroundTaskContextMapFactory.buildTaskContextMap(
2080                                    userId, plid, groupId, portletId, parameterMap,
2081                                    Constants.IMPORT, null, null, file.getName());
2082    
2083                    BackgroundTask backgroundTask =
2084                            backgroundTaskLocalService.addBackgroundTask(
2085                                    userId, groupId, taskName, null,
2086                                    PortletImportBackgroundTaskExecutor.class, taskContextMap,
2087                                    new ServiceContext());
2088    
2089                    backgroundTaskLocalService.addBackgroundTaskAttachment(
2090                            userId, backgroundTask.getBackgroundTaskId(), file.getName(), file);
2091    
2092                    return backgroundTask.getBackgroundTaskId();
2093            }
2094    
2095            @Override
2096            public long importPortletInfoInBackground(
2097                            long userId, String taskName, long plid, long groupId,
2098                            String portletId, Map<String, String[]> parameterMap,
2099                            InputStream is)
2100                    throws PortalException {
2101    
2102                    File file = null;
2103    
2104                    try {
2105                            file = FileUtil.createTempFile("lar");
2106    
2107                            FileUtil.write(file, is);
2108    
2109                            return importPortletInfoInBackground(
2110                                    userId, taskName, plid, groupId, portletId, parameterMap, file);
2111                    }
2112                    catch (IOException ioe) {
2113                            throw new SystemException(ioe);
2114                    }
2115                    finally {
2116                            FileUtil.delete(file);
2117                    }
2118            }
2119    
2120            @Override
2121            public long importPortletInfoInBackground(
2122                            long userId, String taskName, String portletId,
2123                            Map<String, String[]> parameterMap, File file)
2124                    throws PortalException {
2125    
2126                    User user = userPersistence.findByPrimaryKey(userId);
2127    
2128                    Group companyGroup = groupLocalService.getCompanyGroup(
2129                            user.getCompanyId());
2130    
2131                    Group controlPanelGroup = groupPersistence.findByC_F(
2132                            user.getCompanyId(), GroupConstants.CONTROL_PANEL_FRIENDLY_URL);
2133    
2134                    Layout controlPanelLayout = layoutPersistence.findByG_P_T_First(
2135                            controlPanelGroup.getGroupId(), true,
2136                            LayoutConstants.TYPE_CONTROL_PANEL, null);
2137    
2138                    return importPortletInfoInBackground(
2139                            userId, taskName, controlPanelLayout.getPlid(),
2140                            companyGroup.getGroupId(), portletId, parameterMap, file);
2141            }
2142    
2143            @Override
2144            public long importPortletInfoInBackground(
2145                            long userId, String taskName, String portletId,
2146                            Map<String, String[]> parameterMap, InputStream is)
2147                    throws PortalException {
2148    
2149                    File file = null;
2150    
2151                    try {
2152                            file = FileUtil.createTempFile("lar");
2153    
2154                            FileUtil.write(file, is);
2155    
2156                            return importPortletInfoInBackground(
2157                                    userId, taskName, portletId, parameterMap, file);
2158                    }
2159                    catch (IOException ioe) {
2160                            throw new SystemException(ioe);
2161                    }
2162                    finally {
2163                            FileUtil.delete(file);
2164                    }
2165            }
2166    
2167            /**
2168             * Sets the layouts for the group, replacing and prioritizing all layouts of
2169             * the parent layout.
2170             *
2171             * @param  groupId the primary key of the group
2172             * @param  privateLayout whether the layout is private to the group
2173             * @param  parentLayoutId the primary key of the parent layout
2174             * @param  layoutIds the primary keys of the layouts
2175             * @param  serviceContext the service context to be applied
2176             * @throws PortalException if a group or layout with the primary key could
2177             *         not be found, if no layouts were specified, if the first layout
2178             *         was not page-able, if the first layout was hidden, or if some
2179             *         other portal exception occurred
2180             */
2181            @Override
2182            public void setLayouts(
2183                            long groupId, boolean privateLayout, long parentLayoutId,
2184                            long[] layoutIds, ServiceContext serviceContext)
2185                    throws PortalException {
2186    
2187                    if (layoutIds == null) {
2188                            return;
2189                    }
2190    
2191                    if (parentLayoutId == LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
2192                            if (layoutIds.length < 1) {
2193                                    throw new RequiredLayoutException(
2194                                            RequiredLayoutException.AT_LEAST_ONE);
2195                            }
2196    
2197                            Layout layout = layoutPersistence.findByG_P_L(
2198                                    groupId, privateLayout, layoutIds[0]);
2199    
2200                            LayoutType layoutType = layout.getLayoutType();
2201    
2202                            if (!layoutType.isFirstPageable()) {
2203                                    throw new RequiredLayoutException(
2204                                            RequiredLayoutException.FIRST_LAYOUT_TYPE);
2205                            }
2206                    }
2207    
2208                    Set<Long> layoutIdsSet = new LinkedHashSet<Long>();
2209    
2210                    for (long layoutId : layoutIds) {
2211                            layoutIdsSet.add(layoutId);
2212                    }
2213    
2214                    Set<Long> newLayoutIdsSet = new HashSet<Long>();
2215    
2216                    List<Layout> layouts = layoutPersistence.findByG_P_P(
2217                            groupId, privateLayout, parentLayoutId);
2218    
2219                    for (Layout layout : layouts) {
2220                            if (!layoutIdsSet.contains(layout.getLayoutId())) {
2221                                    deleteLayout(layout, true, serviceContext);
2222                            }
2223                            else {
2224                                    newLayoutIdsSet.add(layout.getLayoutId());
2225                            }
2226                    }
2227    
2228                    int priority = 0;
2229    
2230                    for (long layoutId : layoutIdsSet) {
2231                            Layout layout = layoutPersistence.findByG_P_L(
2232                                    groupId, privateLayout, layoutId);
2233    
2234                            layout.setPriority(priority++);
2235    
2236                            layoutPersistence.update(layout);
2237                    }
2238    
2239                    layoutSetLocalService.updatePageCount(groupId, privateLayout);
2240            }
2241    
2242            @Override
2243            public void updateAsset(
2244                            long userId, Layout layout, long[] assetCategoryIds,
2245                            String[] assetTagNames)
2246                    throws PortalException {
2247    
2248                    assetEntryLocalService.updateEntry(
2249                            userId, layout.getGroupId(), layout.getCreateDate(),
2250                            layout.getModifiedDate(), Layout.class.getName(), layout.getPlid(),
2251                            layout.getUuid(), 0, assetCategoryIds, assetTagNames, false, null,
2252                            null, null, ContentTypes.TEXT_HTML,
2253                            layout.getName(LocaleUtil.getDefault()), null, null, null, null, 0,
2254                            0, null, false);
2255            }
2256    
2257            /**
2258             * Updates the friendly URL of the layout.
2259             *
2260             * @param  userId the primary key of the user
2261             * @param  plid the primary key of the layout
2262             * @param  friendlyURL the friendly URL to be assigned
2263             * @param  languageId the primary key of the language
2264             * @return the updated layout
2265             * @throws PortalException if a group or layout with the primary key could
2266             *         not be found
2267             */
2268            @Override
2269            public Layout updateFriendlyURL(
2270                            long userId, long plid, String friendlyURL, String languageId)
2271                    throws PortalException {
2272    
2273                    Date now = new Date();
2274    
2275                    Layout layout = layoutPersistence.findByPrimaryKey(plid);
2276    
2277                    friendlyURL = layoutLocalServiceHelper.getFriendlyURL(
2278                            layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(),
2279                            StringPool.BLANK, friendlyURL);
2280    
2281                    layoutLocalServiceHelper.validateFriendlyURL(
2282                            layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(),
2283                            friendlyURL);
2284    
2285                    layoutFriendlyURLLocalService.updateLayoutFriendlyURL(
2286                            userId, layout.getCompanyId(), layout.getGroupId(),
2287                            layout.getPlid(), layout.isPrivateLayout(), friendlyURL, languageId,
2288                            new ServiceContext());
2289    
2290                    layout.setModifiedDate(now);
2291    
2292                    String defaultLanguageId = LocaleUtil.toLanguageId(
2293                            LocaleUtil.getSiteDefault());
2294    
2295                    if (languageId.equals(defaultLanguageId)) {
2296                            layout.setFriendlyURL(friendlyURL);
2297                    }
2298    
2299                    layoutPersistence.update(layout);
2300    
2301                    return layout;
2302            }
2303    
2304            /**
2305             * Updates the friendly URL of the layout.
2306             *
2307             * @param      plid the primary key of the layout
2308             * @param      friendlyURL the friendly URL to be assigned
2309             * @param      languageId the primary key of the language
2310             * @return     the updated layout
2311             * @throws     PortalException if a group or layout with the primary key
2312             *             could not be found
2313             * @deprecated As of 7.0.0, replaced by {@link #updateFriendlyURL(long,
2314             *             long, String, String)}
2315             */
2316            @Deprecated
2317            @Override
2318            public Layout updateFriendlyURL(
2319                            long plid, String friendlyURL, String languageId)
2320                    throws PortalException {
2321    
2322                    Layout layout = layoutPersistence.findByPrimaryKey(plid);
2323    
2324                    return updateFriendlyURL(
2325                            layout.getUserId(), plid, friendlyURL, languageId);
2326            }
2327    
2328            @Override
2329            public Layout updateIconImage(long plid, byte[] bytes)
2330                    throws PortalException {
2331    
2332                    Layout layout = layoutPersistence.fetchByPrimaryKey(plid);
2333    
2334                    if (layout == null) {
2335                            return null;
2336                    }
2337    
2338                    PortalUtil.updateImageId(layout, true, bytes, "iconImageId", 0, 0, 0);
2339    
2340                    layoutPersistence.update(layout);
2341    
2342                    return layout;
2343            }
2344    
2345            /**
2346             * Updates the layout.
2347             *
2348             * @param  groupId the primary key of the group
2349             * @param  privateLayout whether the layout is private to the group
2350             * @param  layoutId the primary key of the layout
2351             * @param  parentLayoutId the primary key of the layout's new parent layout
2352             * @param  nameMap the locales and localized names to merge (optionally
2353             *         <code>null</code>)
2354             * @param  titleMap the locales and localized titles to merge (optionally
2355             *         <code>null</code>)
2356             * @param  descriptionMap the locales and localized descriptions to merge
2357             *         (optionally <code>null</code>)
2358             * @param  keywordsMap the locales and localized keywords to merge
2359             *         (optionally <code>null</code>)
2360             * @param  robotsMap the locales and localized robots to merge (optionally
2361             *         <code>null</code>)
2362             * @param  type the layout's new type (optionally {@link
2363             *         com.liferay.portal.model.LayoutConstants#TYPE_PORTLET})
2364             * @param  hidden whether the layout is hidden
2365             * @param  friendlyURLMap the layout's locales and localized friendly URLs.
2366             *         To see how the URL is normalized when accessed, see {@link
2367             *         com.liferay.portal.kernel.util.FriendlyURLNormalizerUtil#normalize(
2368             *         String)}.
2369             * @param  iconImage whether the icon image will be updated
2370             * @param  iconBytes the byte array of the layout's new icon image
2371             * @param  serviceContext the service context to be applied. Can set the
2372             *         modification date and expando bridge attributes for the layout.
2373             *         For layouts that are linked to a layout prototype, attributes
2374             *         named <code>layoutPrototypeUuid</code> and
2375             *         <code>layoutPrototypeLinkedEnabled</code> can be specified to
2376             *         provide the unique identifier of the source prototype and a
2377             *         boolean to determine whether a link to it should be enabled to
2378             *         activate propagation of changes made to the linked page in the
2379             *         prototype.
2380             * @return the updated layout
2381             * @throws PortalException if a group or layout with the primary key could
2382             *         not be found, if a unique friendly URL could not be generated, if
2383             *         a valid parent layout ID to use could not be found, if the layout
2384             *         parameters were invalid, or if a portal exception occurred
2385             */
2386            @Override
2387            public Layout updateLayout(
2388                            long groupId, boolean privateLayout, long layoutId,
2389                            long parentLayoutId, Map<Locale, String> nameMap,
2390                            Map<Locale, String> titleMap, Map<Locale, String> descriptionMap,
2391                            Map<Locale, String> keywordsMap, Map<Locale, String> robotsMap,
2392                            String type, boolean hidden, Map<Locale, String> friendlyURLMap,
2393                            boolean iconImage, byte[] iconBytes, ServiceContext serviceContext)
2394                    throws PortalException {
2395    
2396                    // Layout
2397    
2398                    parentLayoutId = layoutLocalServiceHelper.getParentLayoutId(
2399                            groupId, privateLayout, parentLayoutId);
2400                    String name = nameMap.get(LocaleUtil.getSiteDefault());
2401                    friendlyURLMap = layoutLocalServiceHelper.getFriendlyURLMap(
2402                            groupId, privateLayout, layoutId, name, friendlyURLMap);
2403    
2404                    String friendlyURL = friendlyURLMap.get(LocaleUtil.getSiteDefault());
2405    
2406                    layoutLocalServiceHelper.validate(
2407                            groupId, privateLayout, layoutId, parentLayoutId, name, type,
2408                            hidden, friendlyURLMap);
2409    
2410                    layoutLocalServiceHelper.validateParentLayoutId(
2411                            groupId, privateLayout, layoutId, parentLayoutId);
2412    
2413                    Date now = new Date();
2414    
2415                    Layout layout = layoutPersistence.findByG_P_L(
2416                            groupId, privateLayout, layoutId);
2417    
2418                    if (parentLayoutId != layout.getParentLayoutId()) {
2419                            int priority = layoutLocalServiceHelper.getNextPriority(
2420                                    groupId, privateLayout, parentLayoutId,
2421                                    layout.getSourcePrototypeLayoutUuid(), -1);
2422    
2423                            layout.setPriority(priority);
2424                    }
2425    
2426                    layout.setModifiedDate(serviceContext.getModifiedDate(now));
2427                    layout.setParentLayoutId(parentLayoutId);
2428                    layout.setNameMap(nameMap);
2429                    layout.setTitleMap(titleMap);
2430                    layout.setDescriptionMap(descriptionMap);
2431                    layout.setKeywordsMap(keywordsMap);
2432                    layout.setRobotsMap(robotsMap);
2433                    layout.setType(type);
2434                    layout.setHidden(hidden);
2435                    layout.setFriendlyURL(friendlyURL);
2436    
2437                    PortalUtil.updateImageId(
2438                            layout, iconImage, iconBytes, "iconImageId", 0, 0, 0);
2439    
2440                    boolean layoutUpdateable = ParamUtil.getBoolean(
2441                            serviceContext, Sites.LAYOUT_UPDATEABLE, true);
2442    
2443                    UnicodeProperties typeSettingsProperties =
2444                            layout.getTypeSettingsProperties();
2445    
2446                    typeSettingsProperties.put(
2447                            Sites.LAYOUT_UPDATEABLE, String.valueOf(layoutUpdateable));
2448    
2449                    if (privateLayout) {
2450                            typeSettingsProperties.put(
2451                                    "privateLayout", String.valueOf(privateLayout));
2452                    }
2453    
2454                    layout.setTypeSettingsProperties(typeSettingsProperties);
2455    
2456                    String layoutPrototypeUuid = ParamUtil.getString(
2457                            serviceContext, "layoutPrototypeUuid");
2458                    boolean layoutPrototypeLinkEnabled = ParamUtil.getBoolean(
2459                            serviceContext, "layoutPrototypeLinkEnabled");
2460    
2461                    if (Validator.isNotNull(layoutPrototypeUuid)) {
2462                            layout.setLayoutPrototypeUuid(layoutPrototypeUuid);
2463                            layout.setLayoutPrototypeLinkEnabled(layoutPrototypeLinkEnabled);
2464                    }
2465    
2466                    layout.setExpandoBridgeAttributes(serviceContext);
2467    
2468                    layoutPersistence.update(layout);
2469    
2470                    // Layout friendly URLs
2471    
2472                    layoutFriendlyURLLocalService.updateLayoutFriendlyURLs(
2473                            serviceContext.getUserId(), layout.getCompanyId(),
2474                            layout.getGroupId(), layout.getPlid(), layout.isPrivateLayout(),
2475                            friendlyURLMap, serviceContext);
2476    
2477                    // Asset
2478    
2479                    updateAsset(
2480                            serviceContext.getUserId(), layout,
2481                            serviceContext.getAssetCategoryIds(),
2482                            serviceContext.getAssetTagNames());
2483    
2484                    return layout;
2485            }
2486    
2487            /**
2488             * Updates the layout.
2489             *
2490             * @param      groupId the primary key of the group
2491             * @param      privateLayout whether the layout is private to the group
2492             * @param      layoutId the primary key of the layout
2493             * @param      parentLayoutId the primary key of the layout's new parent
2494             *             layout
2495             * @param      nameMap the locales and localized names to merge (optionally
2496             *             <code>null</code>)
2497             * @param      titleMap the locales and localized titles to merge
2498             *             (optionally <code>null</code>)
2499             * @param      descriptionMap the locales and localized descriptions to
2500             *             merge (optionally <code>null</code>)
2501             * @param      keywordsMap the locales and localized keywords to merge
2502             *             (optionally <code>null</code>)
2503             * @param      robotsMap the locales and localized robots to merge
2504             *             (optionally <code>null</code>)
2505             * @param      type the layout's new type (optionally {@link
2506             *             com.liferay.portal.model.LayoutConstants#TYPE_PORTLET})
2507             * @param      hidden whether the layout is hidden
2508             * @param      friendlyURL the layout's new friendly URL (optionally {@link
2509             *             com.liferay.portal.util.PropsValues#DEFAULT_USER_PRIVATE_LAYOUT_FRIENDLY_URL}
2510             *             or {@link
2511             *             com.liferay.portal.util.PropsValues#DEFAULT_USER_PRIVATE_LAYOUT_FRIENDLY_URL}).
2512             *             The default values can be overridden in
2513             *             <code>portal-ext.properties</code> by specifying new values
2514             *             for the corresponding properties defined in {@link
2515             *             com.liferay.portal.util.PropsValues}. To see how the URL is
2516             *             normalized when accessed, see {@link
2517             *             com.liferay.portal.kernel.util.FriendlyURLNormalizerUtil#normalize(
2518             *             String)}.
2519             * @param      iconImage whether the icon image will be updated
2520             * @param      iconBytes the byte array of the layout's new icon image
2521             * @param      serviceContext the service context to be applied. Can set the
2522             *             modification date and expando bridge attributes for the
2523             *             layout. For layouts that are linked to a layout prototype,
2524             *             attributes named <code>layoutPrototypeUuid</code> and
2525             *             <code>layoutPrototypeLinkedEnabled</code> can be specified to
2526             *             provide the unique identifier of the source prototype and a
2527             *             boolean to determine whether a link to it should be enabled
2528             *             to activate propagation of changes made to the linked page in
2529             *             the prototype.
2530             * @return     the updated layout
2531             * @throws     PortalException if a group or layout with the primary key
2532             *             could not be found, if a unique friendly URL could not be
2533             *             generated, if a valid parent layout ID to use could not be
2534             *             found, if the layout parameters were invalid, or if a portal
2535             *             exception occurred
2536             * @deprecated As of 6.2.0, replaced by {@link #updateLayout(long, boolean,
2537             *             long, long, Map, Map, Map, Map, Map, String, boolean, Map,
2538             *             Boolean, byte[], ServiceContext)}
2539             */
2540            @Deprecated
2541            @Override
2542            public Layout updateLayout(
2543                            long groupId, boolean privateLayout, long layoutId,
2544                            long parentLayoutId, Map<Locale, String> nameMap,
2545                            Map<Locale, String> titleMap, Map<Locale, String> descriptionMap,
2546                            Map<Locale, String> keywordsMap, Map<Locale, String> robotsMap,
2547                            String type, boolean hidden, String friendlyURL, Boolean iconImage,
2548                            byte[] iconBytes, ServiceContext serviceContext)
2549                    throws PortalException {
2550    
2551                    Map<Locale, String> friendlyURLMap = new HashMap<Locale, String>();
2552    
2553                    friendlyURLMap.put(LocaleUtil.getSiteDefault(), friendlyURL);
2554    
2555                    return updateLayout(
2556                            groupId, privateLayout, layoutId, parentLayoutId, nameMap, titleMap,
2557                            descriptionMap, keywordsMap, robotsMap, type, hidden,
2558                            friendlyURLMap, iconImage, iconBytes, serviceContext);
2559            }
2560    
2561            /**
2562             * Updates the layout replacing its type settings.
2563             *
2564             * @param  groupId the primary key of the group
2565             * @param  privateLayout whether the layout is private to the group
2566             * @param  layoutId the primary key of the layout
2567             * @param  typeSettings the settings to load the unicode properties object.
2568             *         See {@link com.liferay.portal.kernel.util.UnicodeProperties
2569             *         #fastLoad(String)}.
2570             * @return the updated layout
2571             * @throws PortalException if a matching layout could not be found or if a
2572             *         portal exception occurred
2573             */
2574            @Override
2575            public Layout updateLayout(
2576                            long groupId, boolean privateLayout, long layoutId,
2577                            String typeSettings)
2578                    throws PortalException {
2579    
2580                    Date now = new Date();
2581    
2582                    UnicodeProperties typeSettingsProperties = new UnicodeProperties();
2583    
2584                    typeSettingsProperties.fastLoad(typeSettings);
2585    
2586                    validateTypeSettingsProperties(typeSettingsProperties);
2587    
2588                    Layout layout = layoutPersistence.findByG_P_L(
2589                            groupId, privateLayout, layoutId);
2590    
2591                    layout.setModifiedDate(now);
2592                    layout.setTypeSettings(typeSettingsProperties.toString());
2593    
2594                    layoutPersistence.update(layout);
2595    
2596                    return layout;
2597            }
2598    
2599            /**
2600             * Updates the look and feel of the layout.
2601             *
2602             * @param  groupId the primary key of the group
2603             * @param  privateLayout whether the layout is private to the group
2604             * @param  layoutId the primary key of the layout
2605             * @param  themeId the primary key of the layout's new theme
2606             * @param  colorSchemeId the primary key of the layout's new color scheme
2607             * @param  css the layout's new CSS
2608             * @param  wapTheme whether the theme is for WAP browsers
2609             * @return the updated layout
2610             * @throws PortalException if a matching layout could not be found
2611             */
2612            @Override
2613            public Layout updateLookAndFeel(
2614                            long groupId, boolean privateLayout, long layoutId, String themeId,
2615                            String colorSchemeId, String css, boolean wapTheme)
2616                    throws PortalException {
2617    
2618                    Date now = new Date();
2619    
2620                    Layout layout = layoutPersistence.findByG_P_L(
2621                            groupId, privateLayout, layoutId);
2622    
2623                    layout.setModifiedDate(now);
2624    
2625                    if (wapTheme) {
2626                            layout.setWapThemeId(themeId);
2627                            layout.setWapColorSchemeId(colorSchemeId);
2628                    }
2629                    else {
2630                            layout.setThemeId(themeId);
2631                            layout.setColorSchemeId(colorSchemeId);
2632                            layout.setCss(css);
2633                    }
2634    
2635                    layoutPersistence.update(layout);
2636    
2637                    return layout;
2638            }
2639    
2640            /**
2641             * Updates the name of the layout.
2642             *
2643             * @param  layout the layout to be updated
2644             * @param  name the layout's new name
2645             * @param  languageId the primary key of the language. For more information
2646             *         see {@link java.util.Locale}.
2647             * @return the updated layout
2648             * @throws PortalException if the new name was <code>null</code>
2649             */
2650            @Override
2651            public Layout updateName(Layout layout, String name, String languageId)
2652                    throws PortalException {
2653    
2654                    Date now = new Date();
2655    
2656                    layoutLocalServiceHelper.validateName(name, languageId);
2657    
2658                    layout.setModifiedDate(now);
2659                    layout.setName(name, LocaleUtil.fromLanguageId(languageId));
2660    
2661                    layoutPersistence.update(layout);
2662    
2663                    Group group = layout.getGroup();
2664    
2665                    if (group.isLayoutPrototype()) {
2666                            LayoutPrototype layoutPrototype =
2667                                    layoutPrototypeLocalService.getLayoutPrototype(
2668                                            group.getClassPK());
2669    
2670                            layoutPrototype.setModifiedDate(now);
2671                            layoutPrototype.setName(
2672                                    name, LocaleUtil.fromLanguageId(languageId));
2673    
2674                            layoutPrototypePersistence.update(layoutPrototype);
2675                    }
2676    
2677                    return layout;
2678            }
2679    
2680            /**
2681             * Updates the name of the layout matching the group, layout ID, and
2682             * privacy.
2683             *
2684             * @param  groupId the primary key of the group
2685             * @param  privateLayout whether the layout is private to the group
2686             * @param  layoutId the primary key of the layout
2687             * @param  name the layout's new name
2688             * @param  languageId the primary key of the language. For more information
2689             *         see {@link java.util.Locale}.
2690             * @return the updated layout
2691             * @throws PortalException if a matching layout could not be found or if the
2692             *         new name was <code>null</code>
2693             */
2694            @Override
2695            public Layout updateName(
2696                            long groupId, boolean privateLayout, long layoutId, String name,
2697                            String languageId)
2698                    throws PortalException {
2699    
2700                    Layout layout = layoutPersistence.findByG_P_L(
2701                            groupId, privateLayout, layoutId);
2702    
2703                    return updateName(layout, name, languageId);
2704            }
2705    
2706            /**
2707             * Updates the name of the layout matching the primary key.
2708             *
2709             * @param  plid the primary key of the layout
2710             * @param  name the name to be assigned
2711             * @param  languageId the primary key of the language. For more information
2712             *         see {@link java.util.Locale}.
2713             * @return the updated layout
2714             * @throws PortalException if a layout with the primary key could not be
2715             *         found or if the name was <code>null</code>
2716             */
2717            @Override
2718            public Layout updateName(long plid, String name, String languageId)
2719                    throws PortalException {
2720    
2721                    Layout layout = layoutPersistence.findByPrimaryKey(plid);
2722    
2723                    return updateName(layout, name, languageId);
2724            }
2725    
2726            /**
2727             * Updates the parent layout ID of the layout matching the group, layout ID,
2728             * and privacy.
2729             *
2730             * @param  groupId the primary key of the group
2731             * @param  privateLayout whether the layout is private to the group
2732             * @param  layoutId the primary key of the layout
2733             * @param  parentLayoutId the primary key to be assigned to the parent
2734             *         layout
2735             * @return the matching layout
2736             * @throws PortalException if a valid parent layout ID to use could not be
2737             *         found or if a matching layout could not be found
2738             */
2739            @Override
2740            public Layout updateParentLayoutId(
2741                            long groupId, boolean privateLayout, long layoutId,
2742                            long parentLayoutId)
2743                    throws PortalException {
2744    
2745                    parentLayoutId = layoutLocalServiceHelper.getParentLayoutId(
2746                            groupId, privateLayout, parentLayoutId);
2747    
2748                    layoutLocalServiceHelper.validateParentLayoutId(
2749                            groupId, privateLayout, layoutId, parentLayoutId);
2750    
2751                    Date now = new Date();
2752    
2753                    Layout layout = layoutPersistence.findByG_P_L(
2754                            groupId, privateLayout, layoutId);
2755    
2756                    if (parentLayoutId != layout.getParentLayoutId()) {
2757                            int priority = layoutLocalServiceHelper.getNextPriority(
2758                                    groupId, privateLayout, parentLayoutId,
2759                                    layout.getSourcePrototypeLayoutUuid(), -1);
2760    
2761                            layout.setPriority(priority);
2762                    }
2763    
2764                    layout.setModifiedDate(now);
2765                    layout.setParentLayoutId(parentLayoutId);
2766    
2767                    layoutPersistence.update(layout);
2768    
2769                    return layout;
2770            }
2771    
2772            /**
2773             * Updates the parent layout ID of the layout matching the primary key. If a
2774             * layout matching the parent primary key is found, the layout ID of that
2775             * layout is assigned, otherwise {@link
2776             * com.liferay.portal.model.LayoutConstants#DEFAULT_PARENT_LAYOUT_ID} is
2777             * assigned.
2778             *
2779             * @param  plid the primary key of the layout
2780             * @param  parentPlid the primary key of the parent layout
2781             * @return the layout matching the primary key
2782             * @throws PortalException if a layout with the primary key could not be
2783             *         found or if a valid parent layout ID to use could not be found
2784             */
2785            @Override
2786            public Layout updateParentLayoutId(long plid, long parentPlid)
2787                    throws PortalException {
2788    
2789                    Date now = new Date();
2790    
2791                    Layout layout = layoutPersistence.findByPrimaryKey(plid);
2792    
2793                    long parentLayoutId = LayoutConstants.DEFAULT_PARENT_LAYOUT_ID;
2794    
2795                    if (parentPlid > 0) {
2796                            Layout parentLayout = layoutPersistence.fetchByPrimaryKey(
2797                                    parentPlid);
2798    
2799                            if (parentLayout != null) {
2800                                    parentLayoutId = parentLayout.getLayoutId();
2801                            }
2802                    }
2803    
2804                    parentLayoutId = layoutLocalServiceHelper.getParentLayoutId(
2805                            layout.getGroupId(), layout.isPrivateLayout(), parentLayoutId);
2806    
2807                    layoutLocalServiceHelper.validateParentLayoutId(
2808                            layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(),
2809                            parentLayoutId);
2810    
2811                    if (parentLayoutId != layout.getParentLayoutId()) {
2812                            int priority = layoutLocalServiceHelper.getNextPriority(
2813                                    layout.getGroupId(), layout.isPrivateLayout(), parentLayoutId,
2814                                    layout.getSourcePrototypeLayoutUuid(), -1);
2815    
2816                            layout.setPriority(priority);
2817                    }
2818    
2819                    layout.setModifiedDate(now);
2820                    layout.setParentLayoutId(parentLayoutId);
2821    
2822                    layoutPersistence.update(layout);
2823    
2824                    return layout;
2825            }
2826    
2827            /**
2828             * Updates the parent layout ID and priority of the layout.
2829             *
2830             * @param  plid the primary key of the layout
2831             * @param  parentPlid the primary key of the parent layout
2832             * @param  priority the layout's new priority
2833             * @return the layout matching the primary key
2834             * @throws PortalException if a layout with the primary key could not be
2835             *         found or if a valid parent layout ID could not be found
2836             */
2837            @Override
2838            public Layout updateParentLayoutIdAndPriority(
2839                            long plid, long parentPlid, int priority)
2840                    throws PortalException {
2841    
2842                    Layout layout = updateParentLayoutId(plid, parentPlid);
2843    
2844                    return updatePriority(layout, priority);
2845            }
2846    
2847            /**
2848             * Updates the priorities of the layouts.
2849             *
2850             * @param  groupId the primary key of the group
2851             * @param  privateLayout whether the layout is private to the group
2852             * @throws PortalException if a matching layout could not be found
2853             */
2854            @Override
2855            public void updatePriorities(long groupId, boolean privateLayout)
2856                    throws PortalException {
2857    
2858                    List<Layout> layouts = layoutPersistence.findByG_P(
2859                            groupId, privateLayout);
2860    
2861                    for (Layout layout : layouts) {
2862                            int nextPriority = layoutLocalServiceHelper.getNextPriority(
2863                                    layout.getGroupId(), layout.isPrivateLayout(),
2864                                    layout.getParentLayoutId(),
2865                                    layout.getSourcePrototypeLayoutUuid(), layout.getPriority());
2866    
2867                            layout.setPriority(nextPriority);
2868    
2869                            layoutPersistence.update(layout);
2870                    }
2871            }
2872    
2873            /**
2874             * Updates the priority of the layout.
2875             *
2876             * @param  layout the layout to be updated
2877             * @param  priority the layout's new priority
2878             * @return the updated layout
2879             * @throws PortalException if a portal exception occurred
2880             */
2881            @Override
2882            public Layout updatePriority(Layout layout, int priority)
2883                    throws PortalException {
2884    
2885                    if (layout.getPriority() == priority) {
2886                            return layout;
2887                    }
2888    
2889                    int oldPriority = layout.getPriority();
2890    
2891                    int nextPriority = layoutLocalServiceHelper.getNextPriority(
2892                            layout.getGroupId(), layout.isPrivateLayout(),
2893                            layout.getParentLayoutId(), layout.getSourcePrototypeLayoutUuid(),
2894                            priority);
2895    
2896                    if (oldPriority == nextPriority) {
2897                            return layout;
2898                    }
2899    
2900                    layout.setModifiedDate(new Date());
2901                    layout.setPriority(nextPriority);
2902    
2903                    layoutPersistence.update(layout);
2904    
2905                    List<Layout> layouts = layoutPersistence.findByG_P_P(
2906                            layout.getGroupId(), layout.isPrivateLayout(),
2907                            layout.getParentLayoutId());
2908    
2909                    boolean lessThan = false;
2910    
2911                    if (oldPriority < nextPriority) {
2912                            lessThan = true;
2913                    }
2914    
2915                    layouts = ListUtil.sort(
2916                            layouts, new LayoutPriorityComparator(layout, lessThan));
2917    
2918                    Layout firstLayout = layouts.get(0);
2919    
2920                    layoutLocalServiceHelper.validateFirstLayout(firstLayout);
2921    
2922                    int newPriority = LayoutConstants.FIRST_PRIORITY;
2923    
2924                    for (Layout curLayout : layouts) {
2925                            int curNextPriority = layoutLocalServiceHelper.getNextPriority(
2926                                    layout.getGroupId(), layout.isPrivateLayout(),
2927                                    layout.getParentLayoutId(),
2928                                    curLayout.getSourcePrototypeLayoutUuid(), newPriority++);
2929    
2930                            if (curLayout.getPriority() == curNextPriority) {
2931                                    continue;
2932                            }
2933    
2934                            curLayout.setModifiedDate(layout.getModifiedDate());
2935                            curLayout.setPriority(curNextPriority);
2936    
2937                            layoutPersistence.update(curLayout);
2938    
2939                            if (curLayout.equals(layout)) {
2940                                    layout = curLayout;
2941                            }
2942                    }
2943    
2944                    return layout;
2945            }
2946    
2947            /**
2948             * Updates the priority of the layout matching the group, layout ID, and
2949             * privacy.
2950             *
2951             * @param  groupId the primary key of the group
2952             * @param  privateLayout whether the layout is private to the group
2953             * @param  layoutId the primary key of the layout
2954             * @param  priority the layout's new priority
2955             * @return the updated layout
2956             * @throws PortalException if a matching layout could not be found
2957             */
2958            @Override
2959            public Layout updatePriority(
2960                            long groupId, boolean privateLayout, long layoutId, int priority)
2961                    throws PortalException {
2962    
2963                    Layout layout = layoutPersistence.findByG_P_L(
2964                            groupId, privateLayout, layoutId);
2965    
2966                    return updatePriority(layout, priority);
2967            }
2968    
2969            /**
2970             * Updates the priority of the layout matching the group, layout ID, and
2971             * privacy, setting the layout's priority based on the priorities of the
2972             * next and previous layouts.
2973             *
2974             * @param  groupId the primary key of the group
2975             * @param  privateLayout whether the layout is private to the group
2976             * @param  layoutId the primary key of the layout
2977             * @param  nextLayoutId the primary key of the next layout
2978             * @param  previousLayoutId the primary key of the previous layout
2979             * @return the updated layout
2980             * @throws PortalException if a matching layout could not be found
2981             */
2982            @Override
2983            public Layout updatePriority(
2984                            long groupId, boolean privateLayout, long layoutId,
2985                            long nextLayoutId, long previousLayoutId)
2986                    throws PortalException {
2987    
2988                    Layout layout = getLayout(groupId, privateLayout, layoutId);
2989    
2990                    int priority = layout.getPriority();
2991    
2992                    Layout nextLayout = null;
2993    
2994                    if (nextLayoutId > -1) {
2995                            nextLayout = getLayout(groupId, privateLayout, nextLayoutId);
2996                    }
2997    
2998                    Layout previousLayout = null;
2999    
3000                    if (previousLayoutId > -1) {
3001                            previousLayout = getLayout(
3002                                    groupId, privateLayout, previousLayoutId);
3003                    }
3004    
3005                    if ((nextLayout != null) && (priority > nextLayout.getPriority())) {
3006                            priority = nextLayout.getPriority();
3007                    }
3008                    else if ((previousLayout != null) &&
3009                                     (priority < previousLayout.getPriority())) {
3010    
3011                            priority = previousLayout.getPriority();
3012                    }
3013    
3014                    return updatePriority(layout, priority);
3015            }
3016    
3017            /**
3018             * Updates the priority of the layout matching the primary key.
3019             *
3020             * @param  plid the primary key of the layout
3021             * @param  priority the layout's new priority
3022             * @return the updated layout
3023             * @throws PortalException if a layout with the primary key could not be
3024             *         found
3025             */
3026            @Override
3027            public Layout updatePriority(long plid, int priority)
3028                    throws PortalException {
3029    
3030                    Layout layout = layoutPersistence.findByPrimaryKey(plid);
3031    
3032                    return updatePriority(layout, priority);
3033            }
3034    
3035            /**
3036             * @deprecated As of 6.2.0, with no direct replacement
3037             */
3038            @Deprecated
3039            @Override
3040            @SuppressWarnings("unused")
3041            public void updateScopedPortletNames(
3042                            long groupId, boolean privateLayout, long layoutId,
3043                            Map<Locale, String> nameMap, List<Locale> nameMapModifiedLocales)
3044                    throws PortalException {
3045            }
3046    
3047            /**
3048             * Updates the names of the portlets within scope of the group, the scope of
3049             * the layout's UUID, and the privacy.
3050             *
3051             * @param      groupId the primary key of the group
3052             * @param      privateLayout whether the layout is private to the group
3053             * @param      layoutId the primary key of the layout whose UUID to match
3054             * @param      name the new name for the portlets
3055             * @param      languageId the primary key of the language
3056             * @throws     PortalException if a matching layout could not be found
3057             * @see        com.liferay.portlet.portletconfiguration.action.EditScopeAction
3058             * @deprecated As of 6.2.0, with no direct replacement
3059             */
3060            @Deprecated
3061            @Override
3062            public void updateScopedPortletNames(
3063                            long groupId, boolean privateLayout, long layoutId, String name,
3064                            String languageId)
3065                    throws PortalException {
3066            }
3067    
3068            @Override
3069            public MissingReferences validateImportLayoutsFile(
3070                            long userId, long groupId, boolean privateLayout,
3071                            Map<String, String[]> parameterMap, File file)
3072                    throws PortalException {
3073    
3074                    try {
3075                            LayoutImporter layoutImporter = LayoutImporter.getInstance();
3076    
3077                            return layoutImporter.validateFile(
3078                                    userId, groupId, privateLayout, parameterMap, file);
3079                    }
3080                    catch (PortalException pe) {
3081                            Throwable cause = pe.getCause();
3082    
3083                            if (cause instanceof LocaleException) {
3084                                    throw (PortalException)cause;
3085                            }
3086    
3087                            throw pe;
3088                    }
3089                    catch (SystemException se) {
3090                            throw se;
3091                    }
3092                    catch (Exception e) {
3093                            throw new SystemException(e);
3094                    }
3095            }
3096    
3097            @Override
3098            public MissingReferences validateImportLayoutsFile(
3099                            long userId, long groupId, boolean privateLayout,
3100                            Map<String, String[]> parameterMap, InputStream inputStream)
3101                    throws PortalException {
3102    
3103                    File file = null;
3104    
3105                    try {
3106                            file = FileUtil.createTempFile("lar");
3107    
3108                            FileUtil.write(file, inputStream);
3109    
3110                            return validateImportLayoutsFile(
3111                                    userId, groupId, privateLayout, parameterMap, file);
3112                    }
3113                    catch (IOException ioe) {
3114                            throw new SystemException(ioe);
3115                    }
3116                    finally {
3117                            FileUtil.delete(file);
3118                    }
3119            }
3120    
3121            @Override
3122            public MissingReferences validateImportPortletInfo(
3123                            long userId, long plid, long groupId, String portletId,
3124                            Map<String, String[]> parameterMap, File file)
3125                    throws PortalException {
3126    
3127                    try {
3128                            PortletImporter portletImporter = PortletImporter.getInstance();
3129    
3130                            return portletImporter.validateFile(
3131                                    userId, plid, groupId, portletId, parameterMap, file);
3132                    }
3133                    catch (PortalException pe) {
3134                            Throwable cause = pe.getCause();
3135    
3136                            if (cause instanceof LocaleException) {
3137                                    throw (PortalException)cause;
3138                            }
3139    
3140                            throw pe;
3141                    }
3142                    catch (SystemException se) {
3143                            throw se;
3144                    }
3145                    catch (Exception e) {
3146                            throw new SystemException(e);
3147                    }
3148            }
3149    
3150            @Override
3151            public MissingReferences validateImportPortletInfo(
3152                            long userId, long plid, long groupId, String portletId,
3153                            Map<String, String[]> parameterMap, InputStream inputStream)
3154                    throws PortalException {
3155    
3156                    File file = null;
3157    
3158                    try {
3159                            file = FileUtil.createTempFile("lar");
3160    
3161                            FileUtil.write(file, inputStream);
3162    
3163                            return validateImportPortletInfo(
3164                                    userId, plid, groupId, portletId, parameterMap, file);
3165                    }
3166                    catch (IOException ioe) {
3167                            throw new SystemException(ioe);
3168                    }
3169                    finally {
3170                            FileUtil.delete(file);
3171                    }
3172            }
3173    
3174            protected void validateTypeSettingsProperties(
3175                            UnicodeProperties typeSettingsProperties)
3176                    throws PortalException {
3177    
3178                    String sitemapChangeFrequency = typeSettingsProperties.getProperty(
3179                            "sitemap-changefreq");
3180    
3181                    if (Validator.isNotNull(sitemapChangeFrequency) &&
3182                            !sitemapChangeFrequency.equals("always") &&
3183                            !sitemapChangeFrequency.equals("hourly") &&
3184                            !sitemapChangeFrequency.equals("daily") &&
3185                            !sitemapChangeFrequency.equals("weekly") &&
3186                            !sitemapChangeFrequency.equals("monthly") &&
3187                            !sitemapChangeFrequency.equals("yearly") &&
3188                            !sitemapChangeFrequency.equals("never")) {
3189    
3190                            throw new SitemapChangeFrequencyException();
3191                    }
3192    
3193                    String sitemapInclude = typeSettingsProperties.getProperty(
3194                            "sitemap-include");
3195    
3196                    if (Validator.isNotNull(sitemapInclude) &&
3197                            !sitemapInclude.equals("0") && !sitemapInclude.equals("1")) {
3198    
3199                            throw new SitemapIncludeException();
3200                    }
3201    
3202                    String sitemapPriority = typeSettingsProperties.getProperty(
3203                            "sitemap-priority");
3204    
3205                    if (Validator.isNotNull(sitemapPriority)) {
3206                            try {
3207                                    double priority = Double.parseDouble(sitemapPriority);
3208    
3209                                    if ((priority < 0) || (priority > 1)) {
3210                                            throw new SitemapPagePriorityException();
3211                                    }
3212                            }
3213                            catch (NumberFormatException nfe) {
3214                                    throw new SitemapPagePriorityException();
3215                            }
3216                    }
3217            }
3218    
3219            @BeanReference(type = LayoutLocalServiceHelper.class)
3220            protected LayoutLocalServiceHelper layoutLocalServiceHelper;
3221    
3222    }