001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.service.impl;
016    
017    import com.liferay.portal.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            /**
1104             * Returns the primary key of the default layout for the group
1105             *
1106             * @param  groupId the primary key of the group
1107             * @return the primary key of the default layout for the group (optionally
1108             *         {@link com.liferay.portal.model.LayoutConstants#DEFAULT_PLID})
1109             * @throws SystemException if a system exception occurred
1110             */
1111            @Override
1112            public long getDefaultPlid(long groupId) throws SystemException {
1113                    if (groupId > 0) {
1114                            List<Layout> layouts = layoutPersistence.findByGroupId(
1115                                    groupId, 0, 1);
1116    
1117                            if (layouts.size() > 0) {
1118                                    Layout layout = layouts.get(0);
1119    
1120                                    return layout.getPlid();
1121                            }
1122                    }
1123    
1124                    return LayoutConstants.DEFAULT_PLID;
1125            }
1126    
1127            /**
1128             * Returns primary key of the matching default layout for the group
1129             *
1130             * @param  groupId the primary key of the group
1131             * @param  privateLayout whether the layout is private to the group
1132             * @return the primary key of the default layout for the group; {@link
1133             *         com.liferay.portal.model.LayoutConstants#DEFAULT_PLID}) otherwise
1134             * @throws SystemException if a system exception occurred
1135             */
1136            @Override
1137            public long getDefaultPlid(long groupId, boolean privateLayout)
1138                    throws SystemException {
1139    
1140                    if (groupId > 0) {
1141                            List<Layout> layouts = layoutPersistence.findByG_P(
1142                                    groupId, privateLayout, 0, 1);
1143    
1144                            if (layouts.size() > 0) {
1145                                    Layout layout = layouts.get(0);
1146    
1147                                    return layout.getPlid();
1148                            }
1149                    }
1150    
1151                    return LayoutConstants.DEFAULT_PLID;
1152            }
1153    
1154            /**
1155             * Returns primary key of the default portlet layout for the group
1156             *
1157             * @param  groupId the primary key of the group
1158             * @param  privateLayout whether the layout is private to the group
1159             * @param  portletId the primary key of the portlet
1160             * @return the primary key of the default portlet layout for the group;
1161             *         {@link com.liferay.portal.model.LayoutConstants#DEFAULT_PLID}
1162             *         otherwise
1163             * @throws PortalException if a portlet with the primary key could not be
1164             *         found
1165             * @throws SystemException if a system exception occurred
1166             */
1167            @Override
1168            public long getDefaultPlid(
1169                            long groupId, boolean privateLayout, String portletId)
1170                    throws PortalException, SystemException {
1171    
1172                    if (groupId > 0) {
1173                            List<Layout> layouts = layoutPersistence.findByG_P(
1174                                    groupId, privateLayout);
1175    
1176                            for (Layout layout : layouts) {
1177                                    if (layout.isTypePortlet()) {
1178                                            LayoutTypePortlet layoutTypePortlet =
1179                                                    (LayoutTypePortlet)layout.getLayoutType();
1180    
1181                                            if (layoutTypePortlet.hasPortletId(portletId)) {
1182                                                    return layout.getPlid();
1183                                            }
1184                                    }
1185                            }
1186                    }
1187    
1188                    return LayoutConstants.DEFAULT_PLID;
1189            }
1190    
1191            /**
1192             * Returns the layout for the friendly URL
1193             *
1194             * @param  groupId the primary key of the group
1195             * @param  privateLayout whether the layout is private to the group
1196             * @param  friendlyURL the friendly URL of the layout
1197             * @return the layout for the friendly URL
1198             * @throws PortalException if the friendly URL is <code>null</code> or a
1199             *         matching layout could not be found
1200             * @throws SystemException if a system exception occurred
1201             */
1202            @Override
1203            public Layout getFriendlyURLLayout(
1204                            long groupId, boolean privateLayout, String friendlyURL)
1205                    throws PortalException, SystemException {
1206    
1207                    if (Validator.isNull(friendlyURL)) {
1208                            throw new NoSuchLayoutException();
1209                    }
1210    
1211                    friendlyURL = layoutLocalServiceHelper.getFriendlyURL(friendlyURL);
1212    
1213                    Layout layout = null;
1214    
1215                    List<LayoutFriendlyURL> layoutFriendlyURLs =
1216                            layoutFriendlyURLPersistence.findByG_P_F(
1217                                    groupId, privateLayout, friendlyURL, 0, 1);
1218    
1219                    if (!layoutFriendlyURLs.isEmpty()) {
1220                            LayoutFriendlyURL layoutFriendlyURL = layoutFriendlyURLs.get(0);
1221    
1222                            layout = layoutPersistence.findByPrimaryKey(
1223                                    layoutFriendlyURL.getPlid());
1224                    }
1225    
1226                    if ((layout == null) &&
1227                            friendlyURL.startsWith(StringPool.SLASH) &&
1228                            Validator.isNumber(friendlyURL.substring(1))) {
1229    
1230                            long layoutId = GetterUtil.getLong(friendlyURL.substring(1));
1231    
1232                            layout = layoutPersistence.fetchByG_P_L(
1233                                    groupId, privateLayout, layoutId);
1234                    }
1235    
1236                    if (layout == null) {
1237                            throw new NoSuchLayoutException();
1238                    }
1239    
1240                    return layout;
1241            }
1242    
1243            /**
1244             * Returns the layout matching the primary key, group, and privacy; throws a
1245             * {@link com.liferay.portal.NoSuchLayoutException} otherwise.
1246             *
1247             * @param  groupId the primary key of the group
1248             * @param  privateLayout whether the layout is private to the group
1249             * @param  layoutId the primary key of the layout
1250             * @return the matching layout
1251             * @throws PortalException if a matching layout could not be found
1252             * @throws SystemException if a system exception occurred
1253             */
1254            @Override
1255            public Layout getLayout(long groupId, boolean privateLayout, long layoutId)
1256                    throws PortalException, SystemException {
1257    
1258                    return layoutPersistence.findByG_P_L(groupId, privateLayout, layoutId);
1259            }
1260    
1261            /**
1262             * Returns the layout for the icon image; throws a {@link
1263             * com.liferay.portal.NoSuchLayoutException} otherwise.
1264             *
1265             * @param  iconImageId the primary key of the icon image
1266             * @return Returns the layout for the icon image
1267             * @throws PortalException if an icon image with the primary key could not
1268             *         be found
1269             * @throws SystemException if a system exception occurred
1270             */
1271            @Override
1272            public Layout getLayoutByIconImageId(long iconImageId)
1273                    throws PortalException, SystemException {
1274    
1275                    return layoutPersistence.findByIconImageId(iconImageId);
1276            }
1277    
1278            /**
1279             * Returns all the layouts belonging to the group.
1280             *
1281             * @param  groupId the primary key of the group
1282             * @param  privateLayout whether the layout is private to the group
1283             * @return the matching layouts, or <code>null</code> if no matches were
1284             *         found
1285             * @throws SystemException if a system exception occurred
1286             */
1287            @Override
1288            public List<Layout> getLayouts(long groupId, boolean privateLayout)
1289                    throws SystemException {
1290    
1291                    return layoutPersistence.findByG_P(groupId, privateLayout);
1292            }
1293    
1294            /**
1295             * Returns all the layouts belonging to the group that are children of the
1296             * parent layout.
1297             *
1298             * @param  groupId the primary key of the group
1299             * @param  privateLayout whether the layout is private to the group
1300             * @param  parentLayoutId the primary key of the parent layout
1301             * @return the matching layouts, or <code>null</code> if no matches were
1302             *         found
1303             * @throws SystemException if a system exception occurred
1304             */
1305            @Override
1306            public List<Layout> getLayouts(
1307                            long groupId, boolean privateLayout, long parentLayoutId)
1308                    throws SystemException {
1309    
1310                    return layoutPersistence.findByG_P_P(
1311                            groupId, privateLayout, parentLayoutId);
1312            }
1313    
1314            /**
1315             * Returns a range of all the layouts belonging to the group that are
1316             * children of the parent layout.
1317             *
1318             * <p>
1319             * Useful when paginating results. Returns a maximum of <code>end -
1320             * start</code> instances. <code>start</code> and <code>end</code> are not
1321             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1322             * refers to the first result in the set. Setting both <code>start</code>
1323             * and <code>end</code> to {@link
1324             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1325             * result set.
1326             * </p>
1327             *
1328             * @param  groupId the primary key of the group
1329             * @param  privateLayout whether the layout is private to the group
1330             * @param  parentLayoutId the primary key of the parent layout
1331             * @param  incomplete whether the layout is incomplete
1332             * @param  start the lower bound of the range of layouts
1333             * @param  end the upper bound of the range of layouts (not inclusive)
1334             * @return the matching layouts, or <code>null</code> if no matches were
1335             *         found
1336             * @throws SystemException if a system exception occurred
1337             */
1338            @Override
1339            public List<Layout> getLayouts(
1340                            long groupId, boolean privateLayout, long parentLayoutId,
1341                            boolean incomplete, int start, int end)
1342                    throws SystemException {
1343    
1344                    return layoutPersistence.findByG_P_P(
1345                            groupId, privateLayout, parentLayoutId, start, end);
1346            }
1347    
1348            /**
1349             * Returns all the layouts that match the layout IDs and belong to the
1350             * group.
1351             *
1352             * @param  groupId the primary key of the group
1353             * @param  privateLayout whether the layout is private to the group
1354             * @param  layoutIds the primary keys of the layouts
1355             * @return the matching layouts, or an empty list if no matches were found
1356             * @throws PortalException if a group or layout with the primary key could
1357             *         not be found
1358             * @throws SystemException if a system exception occurred
1359             */
1360            @Override
1361            public List<Layout> getLayouts(
1362                            long groupId, boolean privateLayout, long[] layoutIds)
1363                    throws PortalException, SystemException {
1364    
1365                    List<Layout> layouts = new ArrayList<Layout>();
1366    
1367                    for (long layoutId : layoutIds) {
1368                            Layout layout = getLayout(groupId, privateLayout, layoutId);
1369    
1370                            layouts.add(layout);
1371                    }
1372    
1373                    return layouts;
1374            }
1375    
1376            /**
1377             * Returns all the layouts that match the type and belong to the group.
1378             *
1379             * @param  groupId the primary key of the group
1380             * @param  privateLayout whether the layout is private to the group
1381             * @param  type the type of the layouts (optionally {@link
1382             *         com.liferay.portal.model.LayoutConstants#TYPE_PORTLET})
1383             * @return the matching layouts, or <code>null</code> if no matches were
1384             *         found
1385             * @throws SystemException if a system exception occurred
1386             */
1387            @Override
1388            public List<Layout> getLayouts(
1389                            long groupId, boolean privateLayout, String type)
1390                    throws SystemException {
1391    
1392                    return layoutPersistence.findByG_P_T(groupId, privateLayout, type);
1393            }
1394    
1395            /**
1396             * Returns the layout references for all the layouts that belong to the
1397             * company and belong to the portlet that matches the preferences.
1398             *
1399             * @param  companyId the primary key of the company
1400             * @param  portletId the primary key of the portlet
1401             * @param  preferencesKey the portlet's preference key
1402             * @param  preferencesValue the portlet's preference value
1403             * @return the layout references of the matching layouts
1404             * @throws SystemException if a system exception occurred
1405             */
1406            @Override
1407            public LayoutReference[] getLayouts(
1408                            long companyId, String portletId, String preferencesKey,
1409                            String preferencesValue)
1410                    throws SystemException {
1411    
1412                    List<LayoutReference> layoutReferences = layoutFinder.findByC_P_P(
1413                            companyId, portletId, preferencesKey, preferencesValue);
1414    
1415                    return layoutReferences.toArray(
1416                            new LayoutReference[layoutReferences.size()]);
1417            }
1418    
1419            @Override
1420            public List<Layout> getLayoutsByLayoutPrototypeUuid(
1421                            String layoutPrototypeUuid)
1422                    throws SystemException {
1423    
1424                    return layoutPersistence.findByLayoutPrototypeUuid(layoutPrototypeUuid);
1425            }
1426    
1427            @Override
1428            public int getLayoutsByLayoutPrototypeUuidCount(String layoutPrototypeUuid)
1429                    throws SystemException {
1430    
1431                    return layoutPersistence.countByLayoutPrototypeUuid(
1432                            layoutPrototypeUuid);
1433            }
1434    
1435            @Override
1436            public int getLayoutsCount(Group group, boolean privateLayout)
1437                    throws PortalException, SystemException {
1438    
1439                    return getLayoutsCount(group, privateLayout, true);
1440            }
1441    
1442            @Override
1443            public int getLayoutsCount(
1444                            Group group, boolean privateLayout, boolean includeUserGroups)
1445                    throws PortalException, SystemException {
1446    
1447                    LayoutSet layoutSet = layoutSetPersistence.findByG_P(
1448                            group.getGroupId(), privateLayout);
1449    
1450                    int count = layoutSet.getPageCount();
1451    
1452                    if (!group.isUser() || !includeUserGroups) {
1453                            return count;
1454                    }
1455    
1456                    List<UserGroup> userGroups = userPersistence.getUserGroups(
1457                            group.getClassPK());
1458    
1459                    if (!userGroups.isEmpty()) {
1460                            long userGroupClassNameId = classNameLocalService.getClassNameId(
1461                                    UserGroup.class);
1462    
1463                            for (UserGroup userGroup : userGroups) {
1464                                    Group userGroupGroup = groupPersistence.findByC_C_C(
1465                                            group.getCompanyId(), userGroupClassNameId,
1466                                            userGroup.getUserGroupId());
1467    
1468                                    layoutSet = layoutSetPersistence.findByG_P(
1469                                            userGroupGroup.getGroupId(), privateLayout);
1470    
1471                                    count += layoutSet.getPageCount();
1472                            }
1473                    }
1474    
1475                    return count;
1476            }
1477    
1478            @Override
1479            public int getLayoutsCount(User user, boolean privateLayout)
1480                    throws PortalException, SystemException {
1481    
1482                    return getLayoutsCount(user, privateLayout, true);
1483            }
1484    
1485            @Override
1486            public int getLayoutsCount(
1487                            User user, boolean privateLayout, boolean includeUserGroups)
1488                    throws PortalException, SystemException {
1489    
1490                    long classNameId = classNameLocalService.getClassNameId(User.class);
1491    
1492                    Group group = groupPersistence.findByC_C_C(
1493                            user.getCompanyId(), classNameId, user.getUserId());
1494    
1495                    return getLayoutsCount(group, privateLayout, includeUserGroups);
1496            }
1497    
1498            /**
1499             * Returns the primary key to use for the next layout.
1500             *
1501             * @param  groupId the primary key of the group
1502             * @param  privateLayout whether the layout is private to the group
1503             * @return the primary key to use for the next layout
1504             * @throws SystemException if a system exception occurred
1505             */
1506            @Override
1507            public long getNextLayoutId(long groupId, boolean privateLayout)
1508                    throws SystemException {
1509    
1510                    long nextLayoutId = counterLocalService.increment(
1511                            getCounterName(groupId, privateLayout));
1512    
1513                    if (nextLayoutId == 1) {
1514                            List<Layout> layouts = layoutPersistence.findByG_P(
1515                                    groupId, privateLayout, 0, 1, new LayoutComparator());
1516    
1517                            if (!layouts.isEmpty()) {
1518                                    Layout layout = layouts.get(0);
1519    
1520                                    nextLayoutId = layout.getLayoutId() + 1;
1521    
1522                                    counterLocalService.reset(
1523                                            getCounterName(groupId, privateLayout), nextLayoutId);
1524                            }
1525                    }
1526    
1527                    return nextLayoutId;
1528            }
1529    
1530            /**
1531             * Returns all the layouts without resource permissions
1532             *
1533             * @param  roleId the primary key of the role
1534             * @return all the layouts without resource permissions
1535             * @throws SystemException if a system exception occurred
1536             */
1537            @Override
1538            public List<Layout> getNoPermissionLayouts(long roleId)
1539                    throws SystemException {
1540    
1541                    return layoutFinder.findByNoPermissions(roleId);
1542            }
1543    
1544            /**
1545             * Returns all the layouts whose friendly URLs are <code>null</code>
1546             *
1547             * @return all the layouts whose friendly URLs are <code>null</code>
1548             * @throws SystemException if a system exception occurred
1549             */
1550            @Override
1551            public List<Layout> getNullFriendlyURLLayouts() throws SystemException {
1552                    return layoutFinder.findByNullFriendlyURL();
1553            }
1554    
1555            @Override
1556            public Layout getParentLayout(Layout layout)
1557                    throws PortalException, SystemException {
1558    
1559                    Layout parentLayout = null;
1560    
1561                    if (layout instanceof VirtualLayout) {
1562                            VirtualLayout virtualLayout = (VirtualLayout)layout;
1563    
1564                            Layout sourceLayout = virtualLayout.getSourceLayout();
1565    
1566                            parentLayout = getLayout(
1567                                    sourceLayout.getGroupId(), sourceLayout.isPrivateLayout(),
1568                                    sourceLayout.getParentLayoutId());
1569    
1570                            parentLayout = new VirtualLayout(parentLayout, layout.getGroup());
1571                    }
1572                    else {
1573                            parentLayout = getLayout(
1574                                    layout.getGroupId(), layout.isPrivateLayout(),
1575                                    layout.getParentLayoutId());
1576                    }
1577    
1578                    return parentLayout;
1579            }
1580    
1581            /**
1582             * Returns all the layouts within scope of the group
1583             *
1584             * @param  groupId the primary key of the group
1585             * @param  privateLayout whether the layout is private to the group
1586             * @return the layouts within scope of the group
1587             * @throws SystemException if a system exception occurred
1588             */
1589            @Override
1590            public List<Layout> getScopeGroupLayouts(
1591                            long groupId, boolean privateLayout)
1592                    throws SystemException {
1593    
1594                    return layoutFinder.findByScopeGroup(groupId, privateLayout);
1595            }
1596    
1597            @Override
1598            public boolean hasLayouts(Group group, boolean privateLayout)
1599                    throws PortalException, SystemException {
1600    
1601                    return hasLayouts(group, privateLayout, true);
1602            }
1603    
1604            @Override
1605            public boolean hasLayouts(
1606                            Group group, boolean privateLayout, boolean includeUserGroups)
1607                    throws PortalException, SystemException {
1608    
1609                    LayoutSet layoutSet = layoutSetPersistence.findByG_P(
1610                            group.getGroupId(), privateLayout);
1611    
1612                    if (layoutSet.getPageCount() > 0) {
1613                            return true;
1614                    }
1615    
1616                    if (!group.isUser() || !includeUserGroups) {
1617                            return false;
1618                    }
1619    
1620                    List<UserGroup> userGroups = userPersistence.getUserGroups(
1621                            group.getClassPK());
1622    
1623                    if (!userGroups.isEmpty()) {
1624                            long userGroupClassNameId = classNameLocalService.getClassNameId(
1625                                    UserGroup.class);
1626    
1627                            for (UserGroup userGroup : userGroups) {
1628                                    Group userGroupGroup = groupPersistence.findByC_C_C(
1629                                            group.getCompanyId(), userGroupClassNameId,
1630                                            userGroup.getUserGroupId());
1631    
1632                                    layoutSet = layoutSetPersistence.findByG_P(
1633                                            userGroupGroup.getGroupId(), privateLayout);
1634    
1635                                    if (layoutSet.getPageCount() > 0) {
1636                                            return true;
1637                                    }
1638                            }
1639                    }
1640    
1641                    return false;
1642            }
1643    
1644            /**
1645             * Returns <code>true</code> if the group has any layouts;
1646             * <code>false</code> otherwise.
1647             *
1648             * @param  groupId the primary key of the group
1649             * @param  privateLayout whether the layout is private to the group
1650             * @param  parentLayoutId the primary key of the parent layout
1651             * @return <code>true</code> if the group has any layouts;
1652             *         <code>false</code> otherwise
1653             * @throws SystemException if a system exception occurred
1654             */
1655            @Override
1656            public boolean hasLayouts(
1657                            long groupId, boolean privateLayout, long parentLayoutId)
1658                    throws SystemException {
1659    
1660                    return layoutPersistence.countByG_P_P(
1661                            groupId, privateLayout, parentLayoutId) > 0;
1662            }
1663    
1664            @Override
1665            public boolean hasLayouts(User user, boolean privateLayout)
1666                    throws PortalException, SystemException {
1667    
1668                    return hasLayouts(user, privateLayout, true);
1669            }
1670    
1671            @Override
1672            public boolean hasLayouts(
1673                            User user, boolean privateLayout, boolean includeUserGroups)
1674                    throws PortalException, SystemException {
1675    
1676                    long classNameId = classNameLocalService.getClassNameId(User.class);
1677    
1678                    Group group = groupPersistence.findByC_C_C(
1679                            user.getCompanyId(), classNameId, user.getUserId());
1680    
1681                    return hasLayouts(group, privateLayout, includeUserGroups);
1682            }
1683    
1684            @Override
1685            public boolean hasLayoutSetPrototypeLayout(
1686                            long layoutSetPrototypeId, String layoutUuid)
1687                    throws PortalException, SystemException {
1688    
1689                    LayoutSetPrototype layoutSetPrototype =
1690                            layoutSetPrototypeLocalService.getLayoutSetPrototype(
1691                                    layoutSetPrototypeId);
1692    
1693                    return layoutLocalServiceHelper.hasLayoutSetPrototypeLayout(
1694                            layoutSetPrototype, layoutUuid);
1695            }
1696    
1697            @Override
1698            public boolean hasLayoutSetPrototypeLayout(
1699                            String layoutSetPrototypeUuid, long companyId, String layoutUuid)
1700                    throws PortalException, SystemException {
1701    
1702                    LayoutSetPrototype layoutSetPrototype =
1703                            layoutSetPrototypeLocalService.
1704                                    getLayoutSetPrototypeByUuidAndCompanyId(
1705                                            layoutSetPrototypeUuid, companyId);
1706    
1707                    return layoutLocalServiceHelper.hasLayoutSetPrototypeLayout(
1708                            layoutSetPrototype, layoutUuid);
1709            }
1710    
1711            /**
1712             * Imports the layouts from the byte array.
1713             *
1714             * @param  userId the primary key of the user
1715             * @param  groupId the primary key of the group
1716             * @param  privateLayout whether the layout is private to the group
1717             * @param  parameterMap the mapping of parameters indicating which
1718             *         information will be imported. For information on the keys used in
1719             *         the map see {@link
1720             *         com.liferay.portal.kernel.lar.PortletDataHandlerKeys}.
1721             * @param  bytes the byte array with the data
1722             * @throws PortalException if a group or user with the primary key could not
1723             *         be found, or if some other portal exception occurred
1724             * @throws SystemException if a system exception occurred
1725             * @see    com.liferay.portal.lar.LayoutImporter
1726             */
1727            @Override
1728            public void importLayouts(
1729                            long userId, long groupId, boolean privateLayout,
1730                            Map<String, String[]> parameterMap, byte[] bytes)
1731                    throws PortalException, SystemException {
1732    
1733                    importLayouts(
1734                            userId, groupId, privateLayout, parameterMap,
1735                            new UnsyncByteArrayInputStream(bytes));
1736            }
1737    
1738            /**
1739             * Imports the layouts from the file.
1740             *
1741             * @param  userId the primary key of the user
1742             * @param  groupId the primary key of the group
1743             * @param  privateLayout whether the layout is private to the group
1744             * @param  parameterMap the mapping of parameters indicating which
1745             *         information will be imported. For information on the keys used in
1746             *         the map see {@link
1747             *         com.liferay.portal.kernel.lar.PortletDataHandlerKeys}.
1748             * @param  file the LAR file with the data
1749             * @throws PortalException if a group or user with the primary key could not
1750             *         be found, or if some other portal exception occurred
1751             * @throws SystemException if a system exception occurred
1752             * @see    com.liferay.portal.lar.LayoutImporter
1753             */
1754            @Override
1755            public void importLayouts(
1756                            long userId, long groupId, boolean privateLayout,
1757                            Map<String, String[]> parameterMap, File file)
1758                    throws PortalException, SystemException {
1759    
1760                    try {
1761                            LayoutImporter layoutImporter = new LayoutImporter();
1762    
1763                            layoutImporter.importLayouts(
1764                                    userId, groupId, privateLayout, parameterMap, file);
1765                    }
1766                    catch (PortalException pe) {
1767                            Throwable cause = pe.getCause();
1768    
1769                            if (cause instanceof LocaleException) {
1770                                    throw (PortalException)cause;
1771                            }
1772    
1773                            throw pe;
1774                    }
1775                    catch (SystemException se) {
1776                            throw se;
1777                    }
1778                    catch (Exception e) {
1779                            throw new SystemException(e);
1780                    }
1781            }
1782    
1783            /**
1784             * Imports the layouts from the input stream.
1785             *
1786             * @param  userId the primary key of the user
1787             * @param  groupId the primary key of the group
1788             * @param  privateLayout whether the layout is private to the group
1789             * @param  parameterMap the mapping of parameters indicating which
1790             *         information will be imported. For information on the keys used in
1791             *         the map see {@link
1792             *         com.liferay.portal.kernel.lar.PortletDataHandlerKeys}.
1793             * @param  is the input stream
1794             * @throws PortalException if a group or user with the primary key could not
1795             *         be found, or if some other portal exception occurred
1796             * @throws SystemException if a system exception occurred
1797             * @see    com.liferay.portal.lar.LayoutImporter
1798             */
1799            @Override
1800            public void importLayouts(
1801                            long userId, long groupId, boolean privateLayout,
1802                            Map<String, String[]> parameterMap, InputStream is)
1803                    throws PortalException, SystemException {
1804    
1805                    File file = null;
1806    
1807                    try {
1808                            file = FileUtil.createTempFile("lar");
1809    
1810                            FileUtil.write(file, is);
1811    
1812                            importLayouts(userId, groupId, privateLayout, parameterMap, file);
1813                    }
1814                    catch (IOException ioe) {
1815                            throw new SystemException(ioe);
1816                    }
1817                    finally {
1818                            FileUtil.delete(file);
1819                    }
1820            }
1821    
1822            @Override
1823            public long importLayoutsInBackground(
1824                            long userId, String taskName, long groupId, boolean privateLayout,
1825                            Map<String, String[]> parameterMap, File file)
1826                    throws PortalException, SystemException {
1827    
1828                    Map<String, Serializable> taskContextMap =
1829                            BackgroundTaskContextMapFactory.buildTaskContextMap(
1830                                    userId, groupId, privateLayout, null, parameterMap,
1831                                    Constants.IMPORT, null, null, file.getName());
1832    
1833                    BackgroundTask backgroundTask =
1834                            backgroundTaskLocalService.addBackgroundTask(
1835                                    userId, groupId, taskName, null,
1836                                    LayoutImportBackgroundTaskExecutor.class, taskContextMap,
1837                                    new ServiceContext());
1838    
1839                    backgroundTaskLocalService.addBackgroundTaskAttachment(
1840                            userId, backgroundTask.getBackgroundTaskId(), file.getName(), file);
1841    
1842                    return backgroundTask.getBackgroundTaskId();
1843            }
1844    
1845            @Override
1846            public long importLayoutsInBackground(
1847                            long userId, String taskName, long groupId, boolean privateLayout,
1848                            Map<String, String[]> parameterMap, InputStream is)
1849                    throws PortalException, SystemException {
1850    
1851                    File file = null;
1852    
1853                    try {
1854                            file = FileUtil.createTempFile("lar");
1855    
1856                            FileUtil.write(file, is);
1857    
1858                            return importLayoutsInBackground(
1859                                    userId, taskName, groupId, privateLayout, parameterMap, file);
1860                    }
1861                    catch (IOException ioe) {
1862                            throw new SystemException(ioe);
1863                    }
1864                    finally {
1865                            FileUtil.delete(file);
1866                    }
1867            }
1868    
1869            /**
1870             * Imports the portlet information (categories, permissions, ... etc.) from
1871             * the file.
1872             *
1873             * @param  userId the primary key of the user
1874             * @param  plid the primary key of the target layout
1875             * @param  groupId the primary key of the target group
1876             * @param  portletId the primary key of the portlet
1877             * @param  parameterMap the mapping of parameters indicating which
1878             *         information will be imported. For information on the keys used in
1879             *         the map see {@link
1880             *         com.liferay.portal.kernel.lar.PortletDataHandlerKeys}.
1881             * @param  file the LAR file with the data
1882             * @throws PortalException if a group, layout, portlet or user with the
1883             *         primary key could not be found
1884             * @throws SystemException if a system exception occurred
1885             */
1886            @Override
1887            public void importPortletInfo(
1888                            long userId, long plid, long groupId, String portletId,
1889                            Map<String, String[]> parameterMap, File file)
1890                    throws PortalException, SystemException {
1891    
1892                    try {
1893                            PortletImporter portletImporter = new PortletImporter();
1894    
1895                            portletImporter.importPortletInfo(
1896                                    userId, plid, groupId, portletId, parameterMap, file);
1897                    }
1898                    catch (PortalException pe) {
1899                            Throwable cause = pe.getCause();
1900    
1901                            while (true) {
1902                                    if (cause == null) {
1903                                            break;
1904                                    }
1905    
1906                                    if ((cause instanceof LocaleException) ||
1907                                            (cause instanceof
1908                                                    RecordSetDuplicateRecordSetKeyException) ||
1909                                            (cause instanceof
1910                                                    StructureDuplicateStructureKeyException)) {
1911    
1912                                            throw (PortalException)cause;
1913                                    }
1914    
1915                                    if (cause instanceof PortletDataException) {
1916                                            cause = cause.getCause();
1917                                    }
1918                                    else {
1919                                            break;
1920                                    }
1921                            }
1922    
1923                            throw pe;
1924                    }
1925                    catch (SystemException se) {
1926                            throw se;
1927                    }
1928                    catch (Exception e) {
1929                            throw new SystemException(e);
1930                    }
1931            }
1932    
1933            /**
1934             * Imports the portlet information (categories, permissions, ... etc.) from
1935             * the input stream.
1936             *
1937             * @param  userId the primary key of the user
1938             * @param  plid the primary key of the layout
1939             * @param  groupId the primary key of the group
1940             * @param  portletId the primary key of the portlet
1941             * @param  parameterMap the mapping of parameters indicating which
1942             *         information will be imported. For information on the keys used in
1943             *         the map see {@link
1944             *         com.liferay.portal.kernel.lar.PortletDataHandlerKeys}.
1945             * @param  is the input stream
1946             * @throws PortalException if a group, portlet, layout or user with the
1947             *         primary key could not be found
1948             * @throws SystemException if a system exception occurred
1949             */
1950            @Override
1951            public void importPortletInfo(
1952                            long userId, long plid, long groupId, String portletId,
1953                            Map<String, String[]> parameterMap, InputStream is)
1954                    throws PortalException, SystemException {
1955    
1956                    File file = null;
1957    
1958                    try {
1959                            file = FileUtil.createTempFile("lar");
1960    
1961                            FileUtil.write(file, is);
1962    
1963                            importPortletInfo(
1964                                    userId, plid, groupId, portletId, parameterMap, file);
1965                    }
1966                    catch (IOException ioe) {
1967                            throw new SystemException(ioe);
1968                    }
1969                    finally {
1970                            FileUtil.delete(file);
1971                    }
1972            }
1973    
1974            @Override
1975            public void importPortletInfo(
1976                            long userId, String portletId, Map<String, String[]> parameterMap,
1977                            File file)
1978                    throws PortalException, SystemException {
1979    
1980                    User user = userPersistence.findByPrimaryKey(userId);
1981    
1982                    Group companyGroup = groupLocalService.getCompanyGroup(
1983                            user.getCompanyId());
1984    
1985                    Group controlPanelGroup = groupPersistence.findByC_F(
1986                            user.getCompanyId(), GroupConstants.CONTROL_PANEL_FRIENDLY_URL);
1987    
1988                    Layout controlPanelLayout = layoutPersistence.findByG_P_T_First(
1989                            controlPanelGroup.getGroupId(), true,
1990                            LayoutConstants.TYPE_CONTROL_PANEL, null);
1991    
1992                    importPortletInfo(
1993                            userId, controlPanelLayout.getPlid(), companyGroup.getGroupId(),
1994                            portletId, parameterMap, file);
1995            }
1996    
1997            @Override
1998            public void importPortletInfo(
1999                            long userId, String portletId, Map<String, String[]> parameterMap,
2000                            InputStream is)
2001                    throws PortalException, SystemException {
2002    
2003                    File file = null;
2004    
2005                    try {
2006                            file = FileUtil.createTempFile("lar");
2007    
2008                            FileUtil.write(file, is);
2009    
2010                            importPortletInfo(userId, portletId, parameterMap, file);
2011                    }
2012                    catch (IOException ioe) {
2013                            throw new SystemException(ioe);
2014                    }
2015                    finally {
2016                            FileUtil.delete(file);
2017                    }
2018            }
2019    
2020            @Override
2021            public long importPortletInfoInBackground(
2022                            long userId, String taskName, long plid, long groupId,
2023                            String portletId, Map<String, String[]> parameterMap, File file)
2024                    throws PortalException, SystemException {
2025    
2026                    Map<String, Serializable> taskContextMap =
2027                            BackgroundTaskContextMapFactory.buildTaskContextMap(
2028                                    userId, plid, groupId, portletId, parameterMap,
2029                                    Constants.IMPORT, null, null, file.getName());
2030    
2031                    BackgroundTask backgroundTask =
2032                            backgroundTaskLocalService.addBackgroundTask(
2033                                    userId, groupId, taskName, null,
2034                                    PortletImportBackgroundTaskExecutor.class, taskContextMap,
2035                                    new ServiceContext());
2036    
2037                    backgroundTaskLocalService.addBackgroundTaskAttachment(
2038                            userId, backgroundTask.getBackgroundTaskId(), file.getName(), file);
2039    
2040                    return backgroundTask.getBackgroundTaskId();
2041            }
2042    
2043            @Override
2044            public long importPortletInfoInBackground(
2045                            long userId, String taskName, long plid, long groupId,
2046                            String portletId, Map<String, String[]> parameterMap,
2047                            InputStream is)
2048                    throws PortalException, SystemException {
2049    
2050                    File file = null;
2051    
2052                    try {
2053                            file = FileUtil.createTempFile("lar");
2054    
2055                            FileUtil.write(file, is);
2056    
2057                            return importPortletInfoInBackground(
2058                                    userId, taskName, plid, groupId, portletId, parameterMap, file);
2059                    }
2060                    catch (IOException ioe) {
2061                            throw new SystemException(ioe);
2062                    }
2063                    finally {
2064                            FileUtil.delete(file);
2065                    }
2066            }
2067    
2068            @Override
2069            public long importPortletInfoInBackground(
2070                            long userId, String taskName, String portletId,
2071                            Map<String, String[]> parameterMap, File file)
2072                    throws PortalException, SystemException {
2073    
2074                    User user = userPersistence.findByPrimaryKey(userId);
2075    
2076                    Group companyGroup = groupLocalService.getCompanyGroup(
2077                            user.getCompanyId());
2078    
2079                    Group controlPanelGroup = groupPersistence.findByC_F(
2080                            user.getCompanyId(), GroupConstants.CONTROL_PANEL_FRIENDLY_URL);
2081    
2082                    Layout controlPanelLayout = layoutPersistence.findByG_P_T_First(
2083                            controlPanelGroup.getGroupId(), true,
2084                            LayoutConstants.TYPE_CONTROL_PANEL, null);
2085    
2086                    return importPortletInfoInBackground(
2087                            userId, taskName, controlPanelLayout.getPlid(),
2088                            companyGroup.getGroupId(), portletId, parameterMap, file);
2089            }
2090    
2091            @Override
2092            public long importPortletInfoInBackground(
2093                            long userId, String taskName, String portletId,
2094                            Map<String, String[]> parameterMap, InputStream is)
2095                    throws PortalException, SystemException {
2096    
2097                    File file = null;
2098    
2099                    try {
2100                            file = FileUtil.createTempFile("lar");
2101    
2102                            FileUtil.write(file, is);
2103    
2104                            return importPortletInfoInBackground(
2105                                    userId, taskName, portletId, parameterMap, file);
2106                    }
2107                    catch (IOException ioe) {
2108                            throw new SystemException(ioe);
2109                    }
2110                    finally {
2111                            FileUtil.delete(file);
2112                    }
2113            }
2114    
2115            /**
2116             * Sets the layouts for the group, replacing and prioritizing all layouts of
2117             * the parent layout.
2118             *
2119             * @param  groupId the primary key of the group
2120             * @param  privateLayout whether the layout is private to the group
2121             * @param  parentLayoutId the primary key of the parent layout
2122             * @param  layoutIds the primary keys of the layouts
2123             * @param  serviceContext the service context to be applied
2124             * @throws PortalException if a group or layout with the primary key could
2125             *         not be found, if no layouts were specified, if the first layout
2126             *         was not page-able, if the first layout was hidden, or if some
2127             *         other portal exception occurred
2128             * @throws SystemException if a system exception occurred
2129             */
2130            @Override
2131            public void setLayouts(
2132                            long groupId, boolean privateLayout, long parentLayoutId,
2133                            long[] layoutIds, ServiceContext serviceContext)
2134                    throws PortalException, SystemException {
2135    
2136                    if (layoutIds == null) {
2137                            return;
2138                    }
2139    
2140                    if (parentLayoutId == LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
2141                            if (layoutIds.length < 1) {
2142                                    throw new RequiredLayoutException(
2143                                            RequiredLayoutException.AT_LEAST_ONE);
2144                            }
2145    
2146                            Layout layout = layoutPersistence.findByG_P_L(
2147                                    groupId, privateLayout, layoutIds[0]);
2148    
2149                            if (!PortalUtil.isLayoutFirstPageable(layout.getType())) {
2150                                    throw new RequiredLayoutException(
2151                                            RequiredLayoutException.FIRST_LAYOUT_TYPE);
2152                            }
2153                    }
2154    
2155                    Set<Long> layoutIdsSet = new LinkedHashSet<Long>();
2156    
2157                    for (long layoutId : layoutIds) {
2158                            layoutIdsSet.add(layoutId);
2159                    }
2160    
2161                    Set<Long> newLayoutIdsSet = new HashSet<Long>();
2162    
2163                    List<Layout> layouts = layoutPersistence.findByG_P_P(
2164                            groupId, privateLayout, parentLayoutId);
2165    
2166                    for (Layout layout : layouts) {
2167                            if (!layoutIdsSet.contains(layout.getLayoutId())) {
2168                                    deleteLayout(layout, true, serviceContext);
2169                            }
2170                            else {
2171                                    newLayoutIdsSet.add(layout.getLayoutId());
2172                            }
2173                    }
2174    
2175                    int priority = 0;
2176    
2177                    for (long layoutId : layoutIdsSet) {
2178                            Layout layout = layoutPersistence.findByG_P_L(
2179                                    groupId, privateLayout, layoutId);
2180    
2181                            layout.setPriority(priority++);
2182    
2183                            layoutPersistence.update(layout);
2184                    }
2185    
2186                    layoutSetLocalService.updatePageCount(groupId, privateLayout);
2187            }
2188    
2189            /**
2190             * Updates the friendly URL of the layout.
2191             *
2192             * @param  plid the primary key of the layout
2193             * @param  friendlyURL the friendly URL to be assigned
2194             * @param  languageId the primary key of the language
2195             * @return the updated layout
2196             * @throws PortalException if a group or layout with the primary key could
2197             *         not be found
2198             * @throws SystemException if a system exception occurred
2199             */
2200            @Override
2201            public Layout updateFriendlyURL(
2202                            long plid, String friendlyURL, String languageId)
2203                    throws PortalException, SystemException {
2204    
2205                    Date now = new Date();
2206    
2207                    Layout layout = layoutPersistence.findByPrimaryKey(plid);
2208    
2209                    friendlyURL = layoutLocalServiceHelper.getFriendlyURL(
2210                            layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(),
2211                            StringPool.BLANK, friendlyURL);
2212    
2213                    layoutLocalServiceHelper.validateFriendlyURL(
2214                            layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(),
2215                            friendlyURL);
2216    
2217                    layoutFriendlyURLLocalService.updateLayoutFriendlyURL(
2218                            layout.getUserId(), layout.getCompanyId(), layout.getGroupId(),
2219                            layout.getPlid(), layout.isPrivateLayout(), friendlyURL, languageId,
2220                            new ServiceContext());
2221    
2222                    layout.setModifiedDate(now);
2223    
2224                    String defaultLanguageId = LocaleUtil.toLanguageId(
2225                            LocaleUtil.getSiteDefault());
2226    
2227                    if (languageId.equals(defaultLanguageId)) {
2228                            layout.setFriendlyURL(friendlyURL);
2229                    }
2230    
2231                    layoutPersistence.update(layout);
2232    
2233                    return layout;
2234            }
2235    
2236            /**
2237             * Updates the layout.
2238             *
2239             * @param  groupId the primary key of the group
2240             * @param  privateLayout whether the layout is private to the group
2241             * @param  layoutId the primary key of the layout
2242             * @param  parentLayoutId the primary key of the layout's new parent layout
2243             * @param  nameMap the locales and localized names to merge (optionally
2244             *         <code>null</code>)
2245             * @param  titleMap the locales and localized titles to merge (optionally
2246             *         <code>null</code>)
2247             * @param  descriptionMap the locales and localized descriptions to merge
2248             *         (optionally <code>null</code>)
2249             * @param  keywordsMap the locales and localized keywords to merge
2250             *         (optionally <code>null</code>)
2251             * @param  robotsMap the locales and localized robots to merge (optionally
2252             *         <code>null</code>)
2253             * @param  type the layout's new type (optionally {@link
2254             *         com.liferay.portal.model.LayoutConstants#TYPE_PORTLET})
2255             * @param  hidden whether the layout is hidden
2256             * @param  friendlyURLMap the layout's locales and localized friendly URLs.
2257             *         To see how the URL is normalized when accessed, see {@link
2258             *         com.liferay.portal.kernel.util.FriendlyURLNormalizerUtil#normalize(
2259             *         String)}.
2260             * @param  iconImage whether the icon image will be updated
2261             * @param  iconBytes the byte array of the layout's new icon image
2262             * @param  serviceContext the service context to be applied. Can set the
2263             *         modification date and expando bridge attributes for the layout.
2264             *         For layouts that are linked to a layout prototype, attributes
2265             *         named <code>layoutPrototypeUuid</code> and
2266             *         <code>layoutPrototypeLinkedEnabled</code> can be specified to
2267             *         provide the unique identifier of the source prototype and a
2268             *         boolean to determine whether a link to it should be enabled to
2269             *         activate propagation of changes made to the linked page in the
2270             *         prototype.
2271             * @return the updated layout
2272             * @throws PortalException if a group or layout with the primary key could
2273             *         not be found, if a unique friendly URL could not be generated, if
2274             *         a valid parent layout ID to use could not be found, if the layout
2275             *         parameters were invalid, or if a portal exception occurred
2276             * @throws SystemException if a system exception occurred
2277             */
2278            @Override
2279            public Layout updateLayout(
2280                            long groupId, boolean privateLayout, long layoutId,
2281                            long parentLayoutId, Map<Locale, String> nameMap,
2282                            Map<Locale, String> titleMap, Map<Locale, String> descriptionMap,
2283                            Map<Locale, String> keywordsMap, Map<Locale, String> robotsMap,
2284                            String type, boolean hidden, Map<Locale, String> friendlyURLMap,
2285                            Boolean iconImage, byte[] iconBytes, ServiceContext serviceContext)
2286                    throws PortalException, SystemException {
2287    
2288                    // Layout
2289    
2290                    parentLayoutId = layoutLocalServiceHelper.getParentLayoutId(
2291                            groupId, privateLayout, parentLayoutId);
2292                    String name = nameMap.get(LocaleUtil.getSiteDefault());
2293                    friendlyURLMap = layoutLocalServiceHelper.getFriendlyURLMap(
2294                            groupId, privateLayout, layoutId, name, friendlyURLMap);
2295    
2296                    String friendlyURL = friendlyURLMap.get(LocaleUtil.getSiteDefault());
2297    
2298                    layoutLocalServiceHelper.validate(
2299                            groupId, privateLayout, layoutId, parentLayoutId, name, type,
2300                            hidden, friendlyURLMap);
2301    
2302                    layoutLocalServiceHelper.validateParentLayoutId(
2303                            groupId, privateLayout, layoutId, parentLayoutId);
2304    
2305                    Date now = new Date();
2306    
2307                    Layout layout = layoutPersistence.findByG_P_L(
2308                            groupId, privateLayout, layoutId);
2309    
2310                    if (parentLayoutId != layout.getParentLayoutId()) {
2311                            int priority = layoutLocalServiceHelper.getNextPriority(
2312                                    groupId, privateLayout, parentLayoutId,
2313                                    layout.getSourcePrototypeLayoutUuid(), -1);
2314    
2315                            layout.setPriority(priority);
2316                    }
2317    
2318                    layout.setModifiedDate(serviceContext.getModifiedDate(now));
2319                    layout.setParentLayoutId(parentLayoutId);
2320                    layout.setNameMap(nameMap);
2321                    layout.setTitleMap(titleMap);
2322                    layout.setDescriptionMap(descriptionMap);
2323                    layout.setKeywordsMap(keywordsMap);
2324                    layout.setRobotsMap(robotsMap);
2325                    layout.setType(type);
2326                    layout.setHidden(hidden);
2327                    layout.setFriendlyURL(friendlyURL);
2328    
2329                    if (iconImage != null) {
2330                            layout.setIconImage(iconImage.booleanValue());
2331    
2332                            if (iconImage.booleanValue()) {
2333                                    long iconImageId = layout.getIconImageId();
2334    
2335                                    if (iconImageId <= 0) {
2336                                            iconImageId = counterLocalService.increment();
2337    
2338                                            layout.setIconImageId(iconImageId);
2339                                    }
2340                            }
2341                    }
2342    
2343                    boolean layoutUpdateable = ParamUtil.getBoolean(
2344                            serviceContext, Sites.LAYOUT_UPDATEABLE, true);
2345    
2346                    UnicodeProperties typeSettingsProperties =
2347                            layout.getTypeSettingsProperties();
2348    
2349                    typeSettingsProperties.put(
2350                            Sites.LAYOUT_UPDATEABLE, String.valueOf(layoutUpdateable));
2351    
2352                    if (privateLayout) {
2353                            typeSettingsProperties.put(
2354                                    "privateLayout", String.valueOf(privateLayout));
2355                    }
2356    
2357                    layout.setTypeSettingsProperties(typeSettingsProperties);
2358    
2359                    String layoutPrototypeUuid = ParamUtil.getString(
2360                            serviceContext, "layoutPrototypeUuid");
2361                    boolean layoutPrototypeLinkEnabled = ParamUtil.getBoolean(
2362                            serviceContext, "layoutPrototypeLinkEnabled");
2363    
2364                    if (Validator.isNotNull(layoutPrototypeUuid)) {
2365                            layout.setLayoutPrototypeUuid(layoutPrototypeUuid);
2366                            layout.setLayoutPrototypeLinkEnabled(layoutPrototypeLinkEnabled);
2367                    }
2368    
2369                    layout.setExpandoBridgeAttributes(serviceContext);
2370    
2371                    layoutPersistence.update(layout);
2372    
2373                    // Icon
2374    
2375                    if (iconImage != null) {
2376                            if (!iconImage.booleanValue()) {
2377                                    imageLocalService.deleteImage(layout.getIconImageId());
2378                            }
2379                            else if (ArrayUtil.isNotEmpty(iconBytes)) {
2380                                    imageLocalService.updateImage(
2381                                            layout.getIconImageId(), iconBytes);
2382                            }
2383                    }
2384    
2385                    // Layout friendly URLs
2386    
2387                    layoutFriendlyURLLocalService.updateLayoutFriendlyURLs(
2388                            layout.getUserId(), layout.getCompanyId(), layout.getGroupId(),
2389                            layout.getPlid(), layout.isPrivateLayout(), friendlyURLMap,
2390                            serviceContext);
2391    
2392                    return layout;
2393            }
2394    
2395            /**
2396             * Updates the layout.
2397             *
2398             * @param      groupId the primary key of the group
2399             * @param      privateLayout whether the layout is private to the group
2400             * @param      layoutId the primary key of the layout
2401             * @param      parentLayoutId the primary key of the layout's new parent
2402             *             layout
2403             * @param      nameMap the locales and localized names to merge (optionally
2404             *             <code>null</code>)
2405             * @param      titleMap the locales and localized titles to merge
2406             *             (optionally <code>null</code>)
2407             * @param      descriptionMap the locales and localized descriptions to
2408             *             merge (optionally <code>null</code>)
2409             * @param      keywordsMap the locales and localized keywords to merge
2410             *             (optionally <code>null</code>)
2411             * @param      robotsMap the locales and localized robots to merge
2412             *             (optionally <code>null</code>)
2413             * @param      type the layout's new type (optionally {@link
2414             *             com.liferay.portal.model.LayoutConstants#TYPE_PORTLET})
2415             * @param      hidden whether the layout is hidden
2416             * @param      friendlyURL the layout's new friendly URL (optionally {@link
2417             *             com.liferay.portal.util.PropsValues#DEFAULT_USER_PRIVATE_LAYOUT_FRIENDLY_URL}
2418             *             or {@link
2419             *             com.liferay.portal.util.PropsValues#DEFAULT_USER_PRIVATE_LAYOUT_FRIENDLY_URL}).
2420             *             The default values can be overridden in
2421             *             <code>portal-ext.properties</code> by specifying new values
2422             *             for the corresponding properties defined in {@link
2423             *             com.liferay.portal.util.PropsValues}. To see how the URL is
2424             *             normalized when accessed, see {@link
2425             *             com.liferay.portal.kernel.util.FriendlyURLNormalizerUtil#normalize(
2426             *             String)}.
2427             * @param      iconImage whether the icon image will be updated
2428             * @param      iconBytes the byte array of the layout's new icon image
2429             * @param      serviceContext the service context to be applied. Can set the
2430             *             modification date and expando bridge attributes for the
2431             *             layout. For layouts that are linked to a layout prototype,
2432             *             attributes named <code>layoutPrototypeUuid</code> and
2433             *             <code>layoutPrototypeLinkedEnabled</code> can be specified to
2434             *             provide the unique identifier of the source prototype and a
2435             *             boolean to determine whether a link to it should be enabled
2436             *             to activate propagation of changes made to the linked page in
2437             *             the prototype.
2438             * @return     the updated layout
2439             * @throws     PortalException if a group or layout with the primary key
2440             *             could not be found, if a unique friendly URL could not be
2441             *             generated, if a valid parent layout ID to use could not be
2442             *             found, if the layout parameters were invalid, or if a portal
2443             *             exception occurred
2444             * @throws     SystemException if a system exception occurred
2445             * @deprecated As of 6.2.0, replaced by {@link #updateLayout(long, boolean,
2446             *             long, long, Map, Map, Map, Map, Map, String, boolean, Map,
2447             *             Boolean, byte[], ServiceContext)}
2448             */
2449            @Override
2450            public Layout updateLayout(
2451                            long groupId, boolean privateLayout, long layoutId,
2452                            long parentLayoutId, Map<Locale, String> nameMap,
2453                            Map<Locale, String> titleMap, Map<Locale, String> descriptionMap,
2454                            Map<Locale, String> keywordsMap, Map<Locale, String> robotsMap,
2455                            String type, boolean hidden, String friendlyURL, Boolean iconImage,
2456                            byte[] iconBytes, ServiceContext serviceContext)
2457                    throws PortalException, SystemException {
2458    
2459                    Map<Locale, String> friendlyURLMap = new HashMap<Locale, String>();
2460    
2461                    friendlyURLMap.put(LocaleUtil.getSiteDefault(), friendlyURL);
2462    
2463                    return updateLayout(
2464                            groupId, privateLayout, layoutId, parentLayoutId, nameMap, titleMap,
2465                            descriptionMap, keywordsMap, robotsMap, type, hidden,
2466                            friendlyURLMap, iconImage, iconBytes, serviceContext);
2467            }
2468    
2469            /**
2470             * Updates the layout replacing its type settings.
2471             *
2472             * @param  groupId the primary key of the group
2473             * @param  privateLayout whether the layout is private to the group
2474             * @param  layoutId the primary key of the layout
2475             * @param  typeSettings the settings to load the unicode properties object.
2476             *         See {@link com.liferay.portal.kernel.util.UnicodeProperties
2477             *         #fastLoad(String)}.
2478             * @return the updated layout
2479             * @throws PortalException if a matching layout could not be found or if a
2480             *         portal exception occurred
2481             * @throws SystemException if a system exception occurred
2482             */
2483            @Override
2484            public Layout updateLayout(
2485                            long groupId, boolean privateLayout, long layoutId,
2486                            String typeSettings)
2487                    throws PortalException, SystemException {
2488    
2489                    Date now = new Date();
2490    
2491                    UnicodeProperties typeSettingsProperties = new UnicodeProperties();
2492    
2493                    typeSettingsProperties.fastLoad(typeSettings);
2494    
2495                    validateTypeSettingsProperties(typeSettingsProperties);
2496    
2497                    Layout layout = layoutPersistence.findByG_P_L(
2498                            groupId, privateLayout, layoutId);
2499    
2500                    layout.setModifiedDate(now);
2501                    layout.setTypeSettings(typeSettingsProperties.toString());
2502    
2503                    layoutPersistence.update(layout);
2504    
2505                    return layout;
2506            }
2507    
2508            /**
2509             * Updates the look and feel of the layout.
2510             *
2511             * @param  groupId the primary key of the group
2512             * @param  privateLayout whether the layout is private to the group
2513             * @param  layoutId the primary key of the layout
2514             * @param  themeId the primary key of the layout's new theme
2515             * @param  colorSchemeId the primary key of the layout's new color scheme
2516             * @param  css the layout's new CSS
2517             * @param  wapTheme whether the theme is for WAP browsers
2518             * @return the updated layout
2519             * @throws PortalException if a matching layout could not be found
2520             * @throws SystemException if a system exception occurred
2521             */
2522            @Override
2523            public Layout updateLookAndFeel(
2524                            long groupId, boolean privateLayout, long layoutId, String themeId,
2525                            String colorSchemeId, String css, boolean wapTheme)
2526                    throws PortalException, SystemException {
2527    
2528                    Date now = new Date();
2529    
2530                    Layout layout = layoutPersistence.findByG_P_L(
2531                            groupId, privateLayout, layoutId);
2532    
2533                    layout.setModifiedDate(now);
2534    
2535                    if (wapTheme) {
2536                            layout.setWapThemeId(themeId);
2537                            layout.setWapColorSchemeId(colorSchemeId);
2538                    }
2539                    else {
2540                            layout.setThemeId(themeId);
2541                            layout.setColorSchemeId(colorSchemeId);
2542                            layout.setCss(css);
2543                    }
2544    
2545                    layoutPersistence.update(layout);
2546    
2547                    return layout;
2548            }
2549    
2550            /**
2551             * Updates the name of the layout.
2552             *
2553             * @param  layout the layout to be updated
2554             * @param  name the layout's new name
2555             * @param  languageId the primary key of the language. For more information
2556             *         see {@link java.util.Locale}.
2557             * @return the updated layout
2558             * @throws PortalException if the new name was <code>null</code>
2559             * @throws SystemException if a system exception occurred
2560             */
2561            @Override
2562            public Layout updateName(Layout layout, String name, String languageId)
2563                    throws PortalException, SystemException {
2564    
2565                    Date now = new Date();
2566    
2567                    layoutLocalServiceHelper.validateName(name, languageId);
2568    
2569                    layout.setModifiedDate(now);
2570                    layout.setName(name, LocaleUtil.fromLanguageId(languageId));
2571    
2572                    layoutPersistence.update(layout);
2573    
2574                    Group group = layout.getGroup();
2575    
2576                    if (group.isLayoutPrototype()) {
2577                            LayoutPrototype layoutPrototype =
2578                                    layoutPrototypeLocalService.getLayoutPrototype(
2579                                            group.getClassPK());
2580    
2581                            layoutPrototype.setModifiedDate(now);
2582                            layoutPrototype.setName(
2583                                    name, LocaleUtil.fromLanguageId(languageId));
2584    
2585                            layoutPrototypePersistence.update(layoutPrototype);
2586                    }
2587    
2588                    return layout;
2589            }
2590    
2591            /**
2592             * Updates the name of the layout matching the group, layout ID, and
2593             * privacy.
2594             *
2595             * @param  groupId the primary key of the group
2596             * @param  privateLayout whether the layout is private to the group
2597             * @param  layoutId the primary key of the layout
2598             * @param  name the layout's new name
2599             * @param  languageId the primary key of the language. For more information
2600             *         see {@link java.util.Locale}.
2601             * @return the updated layout
2602             * @throws PortalException if a matching layout could not be found or if the
2603             *         new name was <code>null</code>
2604             * @throws SystemException if a system exception occurred
2605             */
2606            @Override
2607            public Layout updateName(
2608                            long groupId, boolean privateLayout, long layoutId, String name,
2609                            String languageId)
2610                    throws PortalException, SystemException {
2611    
2612                    Layout layout = layoutPersistence.findByG_P_L(
2613                            groupId, privateLayout, layoutId);
2614    
2615                    return layoutLocalService.updateName(layout, name, languageId);
2616            }
2617    
2618            /**
2619             * Updates the name of the layout matching the primary key.
2620             *
2621             * @param  plid the primary key of the layout
2622             * @param  name the name to be assigned
2623             * @param  languageId the primary key of the language. For more information
2624             *         see {@link java.util.Locale}.
2625             * @return the updated layout
2626             * @throws PortalException if a layout with the primary key could not be
2627             *         found or if the name was <code>null</code>
2628             * @throws SystemException if a system exception occurred
2629             */
2630            @Override
2631            public Layout updateName(long plid, String name, String languageId)
2632                    throws PortalException, SystemException {
2633    
2634                    Layout layout = layoutPersistence.findByPrimaryKey(plid);
2635    
2636                    return layoutLocalService.updateName(layout, name, languageId);
2637            }
2638    
2639            /**
2640             * Updates the parent layout ID of the layout matching the group, layout ID,
2641             * and privacy.
2642             *
2643             * @param  groupId the primary key of the group
2644             * @param  privateLayout whether the layout is private to the group
2645             * @param  layoutId the primary key of the layout
2646             * @param  parentLayoutId the primary key to be assigned to the parent
2647             *         layout
2648             * @return the matching layout
2649             * @throws PortalException if a valid parent layout ID to use could not be
2650             *         found or if a matching layout could not be found
2651             * @throws SystemException if a system exception occurred
2652             */
2653            @Override
2654            public Layout updateParentLayoutId(
2655                            long groupId, boolean privateLayout, long layoutId,
2656                            long parentLayoutId)
2657                    throws PortalException, SystemException {
2658    
2659                    parentLayoutId = layoutLocalServiceHelper.getParentLayoutId(
2660                            groupId, privateLayout, parentLayoutId);
2661    
2662                    layoutLocalServiceHelper.validateParentLayoutId(
2663                            groupId, privateLayout, layoutId, parentLayoutId);
2664    
2665                    Date now = new Date();
2666    
2667                    Layout layout = layoutPersistence.findByG_P_L(
2668                            groupId, privateLayout, layoutId);
2669    
2670                    if (parentLayoutId != layout.getParentLayoutId()) {
2671                            int priority = layoutLocalServiceHelper.getNextPriority(
2672                                    groupId, privateLayout, parentLayoutId,
2673                                    layout.getSourcePrototypeLayoutUuid(), -1);
2674    
2675                            layout.setPriority(priority);
2676                    }
2677    
2678                    layout.setModifiedDate(now);
2679                    layout.setParentLayoutId(parentLayoutId);
2680    
2681                    layoutPersistence.update(layout);
2682    
2683                    return layout;
2684            }
2685    
2686            /**
2687             * Updates the parent layout ID of the layout matching the primary key. If a
2688             * layout matching the parent primary key is found, the layout ID of that
2689             * layout is assigned, otherwise {@link
2690             * com.liferay.portal.model.LayoutConstants#DEFAULT_PARENT_LAYOUT_ID} is
2691             * assigned.
2692             *
2693             * @param  plid the primary key of the layout
2694             * @param  parentPlid the primary key of the parent layout
2695             * @return the layout matching the primary key
2696             * @throws PortalException if a layout with the primary key could not be
2697             *         found or if a valid parent layout ID to use could not be found
2698             * @throws SystemException if a system exception occurred
2699             */
2700            @Override
2701            public Layout updateParentLayoutId(long plid, long parentPlid)
2702                    throws PortalException, SystemException {
2703    
2704                    Date now = new Date();
2705    
2706                    Layout layout = layoutPersistence.findByPrimaryKey(plid);
2707    
2708                    long parentLayoutId = LayoutConstants.DEFAULT_PARENT_LAYOUT_ID;
2709    
2710                    if (parentPlid > 0) {
2711                            Layout parentLayout = layoutPersistence.fetchByPrimaryKey(
2712                                    parentPlid);
2713    
2714                            if (parentLayout != null) {
2715                                    parentLayoutId = parentLayout.getLayoutId();
2716                            }
2717                    }
2718    
2719                    parentLayoutId = layoutLocalServiceHelper.getParentLayoutId(
2720                            layout.getGroupId(), layout.isPrivateLayout(), parentLayoutId);
2721    
2722                    layoutLocalServiceHelper.validateParentLayoutId(
2723                            layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(),
2724                            parentLayoutId);
2725    
2726                    if (parentLayoutId != layout.getParentLayoutId()) {
2727                            int priority = layoutLocalServiceHelper.getNextPriority(
2728                                    layout.getGroupId(), layout.isPrivateLayout(), parentLayoutId,
2729                                    layout.getSourcePrototypeLayoutUuid(), -1);
2730    
2731                            layout.setPriority(priority);
2732                    }
2733    
2734                    layout.setModifiedDate(now);
2735                    layout.setParentLayoutId(parentLayoutId);
2736    
2737                    layoutPersistence.update(layout);
2738    
2739                    return layout;
2740            }
2741    
2742            @Override
2743            public Layout updateParentLayoutIdAndPriority(
2744                            long plid, long parentPlid, int priority)
2745                    throws PortalException, SystemException {
2746    
2747                    Layout layout = updateParentLayoutId(plid, parentPlid);
2748    
2749                    return updatePriority(layout, priority);
2750            }
2751    
2752            /**
2753             * Updates the priorities of the layouts.
2754             *
2755             * @param  groupId the primary key of the group
2756             * @param  privateLayout whether the layout is private to the group
2757             * @throws PortalException if a matching layout could not be found
2758             * @throws SystemException if a system exception occurred
2759             */
2760            @Override
2761            public void updatePriorities(long groupId, boolean privateLayout)
2762                    throws PortalException, SystemException {
2763    
2764                    List<Layout> layouts = layoutPersistence.findByG_P(
2765                            groupId, privateLayout);
2766    
2767                    for (Layout layout : layouts) {
2768                            int nextPriority = layoutLocalServiceHelper.getNextPriority(
2769                                    layout.getGroupId(), layout.isPrivateLayout(),
2770                                    layout.getParentLayoutId(),
2771                                    layout.getSourcePrototypeLayoutUuid(), layout.getPriority());
2772    
2773                            layout.setPriority(nextPriority);
2774    
2775                            layoutPersistence.update(layout);
2776                    }
2777            }
2778    
2779            /**
2780             * Updates the priority of the layout.
2781             *
2782             * @param  layout the layout to be updated
2783             * @param  priority the layout's new priority
2784             * @return the updated layout
2785             * @throws PortalException if a portal exception occurred
2786             * @throws SystemException if a system exception occurred
2787             */
2788            @Override
2789            public Layout updatePriority(Layout layout, int priority)
2790                    throws PortalException, SystemException {
2791    
2792                    if (layout.getPriority() == priority) {
2793                            return layout;
2794                    }
2795    
2796                    int oldPriority = layout.getPriority();
2797    
2798                    int nextPriority = layoutLocalServiceHelper.getNextPriority(
2799                            layout.getGroupId(), layout.isPrivateLayout(),
2800                            layout.getParentLayoutId(), layout.getSourcePrototypeLayoutUuid(),
2801                            priority);
2802    
2803                    if (oldPriority == nextPriority) {
2804                            return layout;
2805                    }
2806    
2807                    layout.setModifiedDate(new Date());
2808                    layout.setPriority(nextPriority);
2809    
2810                    layoutPersistence.update(layout);
2811    
2812                    List<Layout> layouts = layoutPersistence.findByG_P_P(
2813                            layout.getGroupId(), layout.isPrivateLayout(),
2814                            layout.getParentLayoutId());
2815    
2816                    boolean lessThan = false;
2817    
2818                    if (oldPriority < nextPriority) {
2819                            lessThan = true;
2820                    }
2821    
2822                    layouts = ListUtil.sort(
2823                            layouts, new LayoutPriorityComparator(layout, lessThan));
2824    
2825                    if (layout.getParentLayoutId() ==
2826                                    LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
2827    
2828                            Layout firstLayout = layouts.get(0);
2829    
2830                            layoutLocalServiceHelper.validateFirstLayout(firstLayout);
2831                    }
2832    
2833                    int newPriority = LayoutConstants.FIRST_PRIORITY;
2834    
2835                    for (Layout curLayout : layouts) {
2836                            int curNextPriority = layoutLocalServiceHelper.getNextPriority(
2837                                    layout.getGroupId(), layout.isPrivateLayout(),
2838                                    layout.getParentLayoutId(),
2839                                    curLayout.getSourcePrototypeLayoutUuid(), newPriority++);
2840    
2841                            if (curLayout.getPriority() == curNextPriority) {
2842                                    continue;
2843                            }
2844    
2845                            curLayout.setModifiedDate(layout.getModifiedDate());
2846                            curLayout.setPriority(curNextPriority);
2847    
2848                            layoutPersistence.update(curLayout);
2849    
2850                            if (curLayout.equals(layout)) {
2851                                    layout = curLayout;
2852                            }
2853                    }
2854    
2855                    return layout;
2856            }
2857    
2858            /**
2859             * Updates the priority of the layout matching the group, layout ID, and
2860             * privacy.
2861             *
2862             * @param  groupId the primary key of the group
2863             * @param  privateLayout whether the layout is private to the group
2864             * @param  layoutId the primary key of the layout
2865             * @param  priority the layout's new priority
2866             * @return the updated layout
2867             * @throws PortalException if a matching layout could not be found
2868             * @throws SystemException if a system exception occurred
2869             */
2870            @Override
2871            public Layout updatePriority(
2872                            long groupId, boolean privateLayout, long layoutId, int priority)
2873                    throws PortalException, SystemException {
2874    
2875                    Layout layout = layoutPersistence.findByG_P_L(
2876                            groupId, privateLayout, layoutId);
2877    
2878                    return updatePriority(layout, priority);
2879            }
2880    
2881            /**
2882             * Updates the priority of the layout matching the group, layout ID, and
2883             * privacy, setting the layout's priority based on the priorities of the
2884             * next and previous layouts.
2885             *
2886             * @param  groupId the primary key of the group
2887             * @param  privateLayout whether the layout is private to the group
2888             * @param  layoutId the primary key of the layout
2889             * @param  nextLayoutId the primary key of the next layout
2890             * @param  previousLayoutId the primary key of the previous layout
2891             * @return the updated layout
2892             * @throws PortalException if a matching layout could not be found
2893             * @throws SystemException if a system exception occurred
2894             */
2895            @Override
2896            public Layout updatePriority(
2897                            long groupId, boolean privateLayout, long layoutId,
2898                            long nextLayoutId, long previousLayoutId)
2899                    throws PortalException, SystemException {
2900    
2901                    Layout layout = getLayout(groupId, privateLayout, layoutId);
2902    
2903                    int priority = layout.getPriority();
2904    
2905                    Layout nextLayout = null;
2906    
2907                    if (nextLayoutId > -1) {
2908                            nextLayout = getLayout(groupId, privateLayout, nextLayoutId);
2909                    }
2910    
2911                    Layout previousLayout = null;
2912    
2913                    if (previousLayoutId > -1) {
2914                            previousLayout = getLayout(
2915                                    groupId, privateLayout, previousLayoutId);
2916                    }
2917    
2918                    if ((nextLayout != null) && (priority > nextLayout.getPriority())) {
2919                            priority = nextLayout.getPriority();
2920                    }
2921                    else if ((previousLayout != null) &&
2922                                     (priority < previousLayout.getPriority())) {
2923    
2924                            priority = previousLayout.getPriority();
2925                    }
2926    
2927                    return updatePriority(layout, priority);
2928            }
2929    
2930            /**
2931             * Updates the priority of the layout matching the primary key.
2932             *
2933             * @param  plid the primary key of the layout
2934             * @param  priority the layout's new priority
2935             * @return the updated layout
2936             * @throws PortalException if a layout with the primary key could not be
2937             *         found
2938             * @throws SystemException if a system exception occurred
2939             */
2940            @Override
2941            public Layout updatePriority(long plid, int priority)
2942                    throws PortalException, SystemException {
2943    
2944                    Layout layout = layoutPersistence.findByPrimaryKey(plid);
2945    
2946                    return updatePriority(layout, priority);
2947            }
2948    
2949            /**
2950             * @deprecated As of 6.2.0, with no direct replacement
2951             */
2952            @Override
2953            @SuppressWarnings("unused")
2954            public void updateScopedPortletNames(
2955                            long groupId, boolean privateLayout, long layoutId,
2956                            Map<Locale, String> nameMap, List<Locale> nameMapModifiedLocales)
2957                    throws PortalException, SystemException {
2958            }
2959    
2960            /**
2961             * Updates the names of the portlets within scope of the group, the scope of
2962             * the layout's UUID, and the privacy.
2963             *
2964             * @param      groupId the primary key of the group
2965             * @param      privateLayout whether the layout is private to the group
2966             * @param      layoutId the primary key of the layout whose UUID to match
2967             * @param      name the new name for the portlets
2968             * @param      languageId the primary key of the language
2969             * @throws     PortalException if a matching layout could not be found
2970             * @throws     SystemException if a system exception occurred
2971             * @see        com.liferay.portlet.portletconfiguration.action.EditScopeAction
2972             * @deprecated As of 6.2.0, with no direct replacement
2973             */
2974            @Override
2975            public void updateScopedPortletNames(
2976                            long groupId, boolean privateLayout, long layoutId, String name,
2977                            String languageId)
2978                    throws PortalException, SystemException {
2979            }
2980    
2981            @Override
2982            public MissingReferences validateImportLayoutsFile(
2983                            long userId, long groupId, boolean privateLayout,
2984                            Map<String, String[]> parameterMap, File file)
2985                    throws PortalException, SystemException {
2986    
2987                    try {
2988                            LayoutImporter layoutImporter = new LayoutImporter();
2989    
2990                            return layoutImporter.validateFile(
2991                                    userId, groupId, privateLayout, parameterMap, file);
2992                    }
2993                    catch (PortalException pe) {
2994                            Throwable cause = pe.getCause();
2995    
2996                            if (cause instanceof LocaleException) {
2997                                    throw (PortalException)cause;
2998                            }
2999    
3000                            throw pe;
3001                    }
3002                    catch (SystemException se) {
3003                            throw se;
3004                    }
3005                    catch (Exception e) {
3006                            throw new SystemException(e);
3007                    }
3008            }
3009    
3010            @Override
3011            public MissingReferences validateImportLayoutsFile(
3012                            long userId, long groupId, boolean privateLayout,
3013                            Map<String, String[]> parameterMap, InputStream inputStream)
3014                    throws PortalException, SystemException {
3015    
3016                    File file = null;
3017    
3018                    try {
3019                            file = FileUtil.createTempFile("lar");
3020    
3021                            FileUtil.write(file, inputStream);
3022    
3023                            return validateImportLayoutsFile(
3024                                    userId, groupId, privateLayout, parameterMap, file);
3025                    }
3026                    catch (IOException ioe) {
3027                            throw new SystemException(ioe);
3028                    }
3029                    finally {
3030                            FileUtil.delete(file);
3031                    }
3032            }
3033    
3034            @Override
3035            public MissingReferences validateImportPortletInfo(
3036                            long userId, long plid, long groupId, String portletId,
3037                            Map<String, String[]> parameterMap, File file)
3038                    throws PortalException, SystemException {
3039    
3040                    try {
3041                            PortletImporter portletImporter = new PortletImporter();
3042    
3043                            return portletImporter.validateFile(
3044                                    userId, plid, groupId, portletId, parameterMap, file);
3045                    }
3046                    catch (PortalException pe) {
3047                            Throwable cause = pe.getCause();
3048    
3049                            if (cause instanceof LocaleException) {
3050                                    throw (PortalException)cause;
3051                            }
3052    
3053                            throw pe;
3054                    }
3055                    catch (SystemException se) {
3056                            throw se;
3057                    }
3058                    catch (Exception e) {
3059                            throw new SystemException(e);
3060                    }
3061            }
3062    
3063            @Override
3064            public MissingReferences validateImportPortletInfo(
3065                            long userId, long plid, long groupId, String portletId,
3066                            Map<String, String[]> parameterMap, InputStream inputStream)
3067                    throws PortalException, SystemException {
3068    
3069                    File file = null;
3070    
3071                    try {
3072                            file = FileUtil.createTempFile("lar");
3073    
3074                            FileUtil.write(file, inputStream);
3075    
3076                            return validateImportPortletInfo(
3077                                    userId, plid, groupId, portletId, parameterMap, file);
3078                    }
3079                    catch (IOException ioe) {
3080                            throw new SystemException(ioe);
3081                    }
3082                    finally {
3083                            FileUtil.delete(file);
3084                    }
3085            }
3086    
3087            protected void validateTypeSettingsProperties(
3088                            UnicodeProperties typeSettingsProperties)
3089                    throws PortalException {
3090    
3091                    String sitemapChangeFrequency = typeSettingsProperties.getProperty(
3092                            "sitemap-changefreq");
3093    
3094                    if (Validator.isNotNull(sitemapChangeFrequency) &&
3095                            !sitemapChangeFrequency.equals("always") &&
3096                            !sitemapChangeFrequency.equals("hourly") &&
3097                            !sitemapChangeFrequency.equals("daily") &&
3098                            !sitemapChangeFrequency.equals("weekly") &&
3099                            !sitemapChangeFrequency.equals("monthly") &&
3100                            !sitemapChangeFrequency.equals("yearly") &&
3101                            !sitemapChangeFrequency.equals("never")) {
3102    
3103                            throw new SitemapChangeFrequencyException();
3104                    }
3105    
3106                    String sitemapInclude = typeSettingsProperties.getProperty(
3107                            "sitemap-include");
3108    
3109                    if (Validator.isNotNull(sitemapInclude) &&
3110                            !sitemapInclude.equals("0") && !sitemapInclude.equals("1")) {
3111    
3112                            throw new SitemapIncludeException();
3113                    }
3114    
3115                    String sitemapPriority = typeSettingsProperties.getProperty(
3116                            "sitemap-priority");
3117    
3118                    if (Validator.isNotNull(sitemapPriority)) {
3119                            try {
3120                                    double priority = Double.parseDouble(sitemapPriority);
3121    
3122                                    if ((priority < 0) || (priority > 1)) {
3123                                            throw new SitemapPagePriorityException();
3124                                    }
3125                            }
3126                            catch (NumberFormatException nfe) {
3127                                    throw new SitemapPagePriorityException();
3128                            }
3129                    }
3130            }
3131    
3132            @BeanReference(type = LayoutLocalServiceHelper.class)
3133            protected LayoutLocalServiceHelper layoutLocalServiceHelper;
3134    
3135    }