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