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