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                    Layout firstLayout = layouts.get(0);
2826    
2827                    layoutLocalServiceHelper.validateFirstLayout(firstLayout);
2828    
2829                    int newPriority = LayoutConstants.FIRST_PRIORITY;
2830    
2831                    for (Layout curLayout : layouts) {
2832                            int curNextPriority = layoutLocalServiceHelper.getNextPriority(
2833                                    layout.getGroupId(), layout.isPrivateLayout(),
2834                                    layout.getParentLayoutId(),
2835                                    curLayout.getSourcePrototypeLayoutUuid(), newPriority++);
2836    
2837                            if (curLayout.getPriority() == curNextPriority) {
2838                                    continue;
2839                            }
2840    
2841                            curLayout.setModifiedDate(layout.getModifiedDate());
2842                            curLayout.setPriority(curNextPriority);
2843    
2844                            layoutPersistence.update(curLayout);
2845    
2846                            if (curLayout.equals(layout)) {
2847                                    layout = curLayout;
2848                            }
2849                    }
2850    
2851                    return layout;
2852            }
2853    
2854            /**
2855             * Updates the priority of the layout matching the group, layout ID, and
2856             * privacy.
2857             *
2858             * @param  groupId the primary key of the group
2859             * @param  privateLayout whether the layout is private to the group
2860             * @param  layoutId the primary key of the layout
2861             * @param  priority the layout's new priority
2862             * @return the updated layout
2863             * @throws PortalException if a matching layout could not be found
2864             * @throws SystemException if a system exception occurred
2865             */
2866            @Override
2867            public Layout updatePriority(
2868                            long groupId, boolean privateLayout, long layoutId, int priority)
2869                    throws PortalException, SystemException {
2870    
2871                    Layout layout = layoutPersistence.findByG_P_L(
2872                            groupId, privateLayout, layoutId);
2873    
2874                    return updatePriority(layout, priority);
2875            }
2876    
2877            /**
2878             * Updates the priority of the layout matching the group, layout ID, and
2879             * privacy, setting the layout's priority based on the priorities of the
2880             * next and previous layouts.
2881             *
2882             * @param  groupId the primary key of the group
2883             * @param  privateLayout whether the layout is private to the group
2884             * @param  layoutId the primary key of the layout
2885             * @param  nextLayoutId the primary key of the next layout
2886             * @param  previousLayoutId the primary key of the previous layout
2887             * @return the updated layout
2888             * @throws PortalException if a matching layout could not be found
2889             * @throws SystemException if a system exception occurred
2890             */
2891            @Override
2892            public Layout updatePriority(
2893                            long groupId, boolean privateLayout, long layoutId,
2894                            long nextLayoutId, long previousLayoutId)
2895                    throws PortalException, SystemException {
2896    
2897                    Layout layout = getLayout(groupId, privateLayout, layoutId);
2898    
2899                    int priority = layout.getPriority();
2900    
2901                    Layout nextLayout = null;
2902    
2903                    if (nextLayoutId > -1) {
2904                            nextLayout = getLayout(groupId, privateLayout, nextLayoutId);
2905                    }
2906    
2907                    Layout previousLayout = null;
2908    
2909                    if (previousLayoutId > -1) {
2910                            previousLayout = getLayout(
2911                                    groupId, privateLayout, previousLayoutId);
2912                    }
2913    
2914                    if ((nextLayout != null) && (priority > nextLayout.getPriority())) {
2915                            priority = nextLayout.getPriority();
2916                    }
2917                    else if ((previousLayout != null) &&
2918                                     (priority < previousLayout.getPriority())) {
2919    
2920                            priority = previousLayout.getPriority();
2921                    }
2922    
2923                    return updatePriority(layout, priority);
2924            }
2925    
2926            /**
2927             * Updates the priority of the layout matching the primary key.
2928             *
2929             * @param  plid the primary key of the layout
2930             * @param  priority the layout's new priority
2931             * @return the updated layout
2932             * @throws PortalException if a layout with the primary key could not be
2933             *         found
2934             * @throws SystemException if a system exception occurred
2935             */
2936            @Override
2937            public Layout updatePriority(long plid, int priority)
2938                    throws PortalException, SystemException {
2939    
2940                    Layout layout = layoutPersistence.findByPrimaryKey(plid);
2941    
2942                    return updatePriority(layout, priority);
2943            }
2944    
2945            /**
2946             * @deprecated As of 6.2.0, with no direct replacement
2947             */
2948            @Override
2949            @SuppressWarnings("unused")
2950            public void updateScopedPortletNames(
2951                            long groupId, boolean privateLayout, long layoutId,
2952                            Map<Locale, String> nameMap, List<Locale> nameMapModifiedLocales)
2953                    throws PortalException, SystemException {
2954            }
2955    
2956            /**
2957             * Updates the names of the portlets within scope of the group, the scope of
2958             * the layout's UUID, and the privacy.
2959             *
2960             * @param      groupId the primary key of the group
2961             * @param      privateLayout whether the layout is private to the group
2962             * @param      layoutId the primary key of the layout whose UUID to match
2963             * @param      name the new name for the portlets
2964             * @param      languageId the primary key of the language
2965             * @throws     PortalException if a matching layout could not be found
2966             * @throws     SystemException if a system exception occurred
2967             * @see        com.liferay.portlet.portletconfiguration.action.EditScopeAction
2968             * @deprecated As of 6.2.0, with no direct replacement
2969             */
2970            @Override
2971            public void updateScopedPortletNames(
2972                            long groupId, boolean privateLayout, long layoutId, String name,
2973                            String languageId)
2974                    throws PortalException, SystemException {
2975            }
2976    
2977            @Override
2978            public MissingReferences validateImportLayoutsFile(
2979                            long userId, long groupId, boolean privateLayout,
2980                            Map<String, String[]> parameterMap, File file)
2981                    throws PortalException, SystemException {
2982    
2983                    try {
2984                            LayoutImporter layoutImporter = new LayoutImporter();
2985    
2986                            return layoutImporter.validateFile(
2987                                    userId, groupId, privateLayout, parameterMap, file);
2988                    }
2989                    catch (PortalException pe) {
2990                            Throwable cause = pe.getCause();
2991    
2992                            if (cause instanceof LocaleException) {
2993                                    throw (PortalException)cause;
2994                            }
2995    
2996                            throw pe;
2997                    }
2998                    catch (SystemException se) {
2999                            throw se;
3000                    }
3001                    catch (Exception e) {
3002                            throw new SystemException(e);
3003                    }
3004            }
3005    
3006            @Override
3007            public MissingReferences validateImportLayoutsFile(
3008                            long userId, long groupId, boolean privateLayout,
3009                            Map<String, String[]> parameterMap, InputStream inputStream)
3010                    throws PortalException, SystemException {
3011    
3012                    File file = null;
3013    
3014                    try {
3015                            file = FileUtil.createTempFile("lar");
3016    
3017                            FileUtil.write(file, inputStream);
3018    
3019                            return validateImportLayoutsFile(
3020                                    userId, groupId, privateLayout, parameterMap, file);
3021                    }
3022                    catch (IOException ioe) {
3023                            throw new SystemException(ioe);
3024                    }
3025                    finally {
3026                            FileUtil.delete(file);
3027                    }
3028            }
3029    
3030            @Override
3031            public MissingReferences validateImportPortletInfo(
3032                            long userId, long plid, long groupId, String portletId,
3033                            Map<String, String[]> parameterMap, File file)
3034                    throws PortalException, SystemException {
3035    
3036                    try {
3037                            PortletImporter portletImporter = new PortletImporter();
3038    
3039                            return portletImporter.validateFile(
3040                                    userId, plid, groupId, portletId, parameterMap, file);
3041                    }
3042                    catch (PortalException pe) {
3043                            Throwable cause = pe.getCause();
3044    
3045                            if (cause instanceof LocaleException) {
3046                                    throw (PortalException)cause;
3047                            }
3048    
3049                            throw pe;
3050                    }
3051                    catch (SystemException se) {
3052                            throw se;
3053                    }
3054                    catch (Exception e) {
3055                            throw new SystemException(e);
3056                    }
3057            }
3058    
3059            @Override
3060            public MissingReferences validateImportPortletInfo(
3061                            long userId, long plid, long groupId, String portletId,
3062                            Map<String, String[]> parameterMap, InputStream inputStream)
3063                    throws PortalException, SystemException {
3064    
3065                    File file = null;
3066    
3067                    try {
3068                            file = FileUtil.createTempFile("lar");
3069    
3070                            FileUtil.write(file, inputStream);
3071    
3072                            return validateImportPortletInfo(
3073                                    userId, plid, groupId, portletId, parameterMap, file);
3074                    }
3075                    catch (IOException ioe) {
3076                            throw new SystemException(ioe);
3077                    }
3078                    finally {
3079                            FileUtil.delete(file);
3080                    }
3081            }
3082    
3083            protected void validateTypeSettingsProperties(
3084                            UnicodeProperties typeSettingsProperties)
3085                    throws PortalException {
3086    
3087                    String sitemapChangeFrequency = typeSettingsProperties.getProperty(
3088                            "sitemap-changefreq");
3089    
3090                    if (Validator.isNotNull(sitemapChangeFrequency) &&
3091                            !sitemapChangeFrequency.equals("always") &&
3092                            !sitemapChangeFrequency.equals("hourly") &&
3093                            !sitemapChangeFrequency.equals("daily") &&
3094                            !sitemapChangeFrequency.equals("weekly") &&
3095                            !sitemapChangeFrequency.equals("monthly") &&
3096                            !sitemapChangeFrequency.equals("yearly") &&
3097                            !sitemapChangeFrequency.equals("never")) {
3098    
3099                            throw new SitemapChangeFrequencyException();
3100                    }
3101    
3102                    String sitemapInclude = typeSettingsProperties.getProperty(
3103                            "sitemap-include");
3104    
3105                    if (Validator.isNotNull(sitemapInclude) &&
3106                            !sitemapInclude.equals("0") && !sitemapInclude.equals("1")) {
3107    
3108                            throw new SitemapIncludeException();
3109                    }
3110    
3111                    String sitemapPriority = typeSettingsProperties.getProperty(
3112                            "sitemap-priority");
3113    
3114                    if (Validator.isNotNull(sitemapPriority)) {
3115                            try {
3116                                    double priority = Double.parseDouble(sitemapPriority);
3117    
3118                                    if ((priority < 0) || (priority > 1)) {
3119                                            throw new SitemapPagePriorityException();
3120                                    }
3121                            }
3122                            catch (NumberFormatException nfe) {
3123                                    throw new SitemapPagePriorityException();
3124                            }
3125                    }
3126            }
3127    
3128            @BeanReference(type = LayoutLocalServiceHelper.class)
3129            protected LayoutLocalServiceHelper layoutLocalServiceHelper;
3130    
3131    }