001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.layoutsadmin.lar;
016    
017    import com.liferay.counter.service.CounterLocalServiceUtil;
018    import com.liferay.portal.NoSuchLayoutException;
019    import com.liferay.portal.kernel.bean.PortalBeanLocatorUtil;
020    import com.liferay.portal.kernel.dao.orm.QueryUtil;
021    import com.liferay.portal.kernel.exception.PortalException;
022    import com.liferay.portal.kernel.json.JSONFactoryUtil;
023    import com.liferay.portal.kernel.json.JSONObject;
024    import com.liferay.portal.kernel.lar.BaseStagedModelDataHandler;
025    import com.liferay.portal.kernel.lar.ExportImportPathUtil;
026    import com.liferay.portal.kernel.lar.PortletDataContext;
027    import com.liferay.portal.kernel.lar.PortletDataException;
028    import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
029    import com.liferay.portal.kernel.lar.StagedModelDataHandlerUtil;
030    import com.liferay.portal.kernel.lar.StagedModelModifiedDateComparator;
031    import com.liferay.portal.kernel.log.Log;
032    import com.liferay.portal.kernel.log.LogFactoryUtil;
033    import com.liferay.portal.kernel.staging.LayoutStagingUtil;
034    import com.liferay.portal.kernel.staging.StagingUtil;
035    import com.liferay.portal.kernel.util.ArrayUtil;
036    import com.liferay.portal.kernel.util.CharPool;
037    import com.liferay.portal.kernel.util.Constants;
038    import com.liferay.portal.kernel.util.GetterUtil;
039    import com.liferay.portal.kernel.util.ListUtil;
040    import com.liferay.portal.kernel.util.LocaleUtil;
041    import com.liferay.portal.kernel.util.MapUtil;
042    import com.liferay.portal.kernel.util.StringBundler;
043    import com.liferay.portal.kernel.util.StringPool;
044    import com.liferay.portal.kernel.util.StringUtil;
045    import com.liferay.portal.kernel.util.UnicodeProperties;
046    import com.liferay.portal.kernel.util.Validator;
047    import com.liferay.portal.kernel.workflow.WorkflowConstants;
048    import com.liferay.portal.kernel.xml.Element;
049    import com.liferay.portal.model.Group;
050    import com.liferay.portal.model.Image;
051    import com.liferay.portal.model.Layout;
052    import com.liferay.portal.model.LayoutBranch;
053    import com.liferay.portal.model.LayoutConstants;
054    import com.liferay.portal.model.LayoutFriendlyURL;
055    import com.liferay.portal.model.LayoutPrototype;
056    import com.liferay.portal.model.LayoutRevision;
057    import com.liferay.portal.model.LayoutSet;
058    import com.liferay.portal.model.LayoutStagingHandler;
059    import com.liferay.portal.model.LayoutTemplate;
060    import com.liferay.portal.model.LayoutTypePortlet;
061    import com.liferay.portal.model.LayoutTypePortletConstants;
062    import com.liferay.portal.service.GroupLocalServiceUtil;
063    import com.liferay.portal.service.ImageLocalServiceUtil;
064    import com.liferay.portal.service.LayoutFriendlyURLLocalServiceUtil;
065    import com.liferay.portal.service.LayoutLocalServiceUtil;
066    import com.liferay.portal.service.LayoutPrototypeLocalServiceUtil;
067    import com.liferay.portal.service.LayoutSetLocalServiceUtil;
068    import com.liferay.portal.service.LayoutTemplateLocalServiceUtil;
069    import com.liferay.portal.service.PortletLocalServiceUtil;
070    import com.liferay.portal.service.ResourceLocalServiceUtil;
071    import com.liferay.portal.service.ServiceContext;
072    import com.liferay.portal.service.ServiceContextThreadLocal;
073    import com.liferay.portal.service.impl.LayoutLocalServiceHelper;
074    import com.liferay.portal.util.PropsValues;
075    import com.liferay.portlet.journal.NoSuchArticleException;
076    import com.liferay.portlet.journal.model.JournalArticle;
077    import com.liferay.portlet.journal.service.JournalArticleLocalServiceUtil;
078    import com.liferay.portlet.journal.service.JournalContentSearchLocalServiceUtil;
079    import com.liferay.portlet.sites.util.SitesUtil;
080    
081    import java.io.IOException;
082    
083    import java.util.Date;
084    import java.util.HashMap;
085    import java.util.List;
086    import java.util.Locale;
087    import java.util.Map;
088    
089    /**
090     * @author Mate Thurzo
091     */
092    public class LayoutStagedModelDataHandler
093            extends BaseStagedModelDataHandler<Layout> {
094    
095            public static final String[] CLASS_NAMES = {Layout.class.getName()};
096    
097            @Override
098            public void deleteStagedModel(
099                            String uuid, long groupId, String className, String extraData)
100                    throws PortalException {
101    
102                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject(
103                            extraData);
104    
105                    boolean privateLayout = extraDataJSONObject.getBoolean("privateLayout");
106    
107                    Layout layout = LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
108                            uuid, groupId, privateLayout);
109    
110                    if (layout != null) {
111                            LayoutLocalServiceUtil.deleteLayout(
112                                    layout, true, new ServiceContext());
113                    }
114            }
115    
116            @Override
117            public Layout fetchStagedModelByUuidAndCompanyId(
118                    String uuid, long companyId) {
119    
120                    List<Layout> layouts =
121                            LayoutLocalServiceUtil.getLayoutsByUuidAndCompanyId(
122                                    uuid, companyId, QueryUtil.ALL_POS, QueryUtil.ALL_POS,
123                                    new StagedModelModifiedDateComparator<Layout>());
124    
125                    if (ListUtil.isEmpty(layouts)) {
126                            return null;
127                    }
128    
129                    return layouts.get(0);
130            }
131    
132            @Override
133            public String[] getClassNames() {
134                    return CLASS_NAMES;
135            }
136    
137            @Override
138            public String getDisplayName(Layout layout) {
139                    return layout.getNameCurrentValue();
140            }
141    
142            @Override
143            public Map<String, String> getReferenceAttributes(
144                    PortletDataContext portletDataContext, Layout layout) {
145    
146                    Map<String, String> referenceAttributes = new HashMap<String, String>();
147    
148                    referenceAttributes.put(
149                            "private-layout", String.valueOf(layout.isPrivateLayout()));
150                    referenceAttributes.put(
151                            "layout-id", String.valueOf(layout.getLayoutId()));
152    
153                    return referenceAttributes;
154            }
155    
156            @Override
157            public void importMissingReference(
158                            PortletDataContext portletDataContext, Element referenceElement)
159                    throws PortletDataException {
160    
161                    importMissingGroupReference(portletDataContext, referenceElement);
162    
163                    String uuid = referenceElement.attributeValue("uuid");
164    
165                    Map<Long, Long> groupIds =
166                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
167                                    Group.class);
168    
169                    long liveGroupId = GetterUtil.getLong(
170                            referenceElement.attributeValue("live-group-id"));
171    
172                    liveGroupId = MapUtil.getLong(groupIds, liveGroupId);
173    
174                    boolean privateLayout = GetterUtil.getBoolean(
175                            referenceElement.attributeValue("private-layout"));
176    
177                    Layout existingLayout = null;
178    
179                    existingLayout = fetchMissingReference(
180                            uuid, liveGroupId, privateLayout);
181    
182                    Map<Long, Layout> layouts =
183                            (Map<Long, Layout>)portletDataContext.getNewPrimaryKeysMap(
184                                    Layout.class + ".layout");
185    
186                    long layoutId = GetterUtil.getLong(
187                            referenceElement.attributeValue("layout-id"));
188    
189                    layouts.put(layoutId, existingLayout);
190    
191                    Map<Long, Long> layoutPlids =
192                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
193                                    Layout.class);
194    
195                    long plid = GetterUtil.getLong(
196                            referenceElement.attributeValue("class-pk"));
197    
198                    layoutPlids.put(plid, existingLayout.getPlid());
199            }
200    
201            @Override
202            public boolean validateReference(
203                    PortletDataContext portletDataContext, Element referenceElement) {
204    
205                    validateMissingGroupReference(portletDataContext, referenceElement);
206    
207                    String uuid = referenceElement.attributeValue("uuid");
208    
209                    Map<Long, Long> groupIds =
210                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
211                                    Group.class);
212    
213                    long liveGroupId = GetterUtil.getLong(
214                            referenceElement.attributeValue("live-group-id"));
215    
216                    liveGroupId = MapUtil.getLong(groupIds, liveGroupId);
217    
218                    boolean privateLayout = GetterUtil.getBoolean(
219                            referenceElement.attributeValue("private-layout"));
220    
221                    Layout existingLayout = fetchMissingReference(
222                            uuid, liveGroupId, privateLayout);
223    
224                    if (existingLayout == null) {
225                            return false;
226                    }
227    
228                    return true;
229            }
230    
231            protected String[] appendPortletIds(
232                    String[] portletIds, String[] newPortletIds, String portletsMergeMode) {
233    
234                    for (String portletId : newPortletIds) {
235                            if (ArrayUtil.contains(portletIds, portletId)) {
236                                    continue;
237                            }
238    
239                            if (portletsMergeMode.equals(
240                                            PortletDataHandlerKeys.PORTLETS_MERGE_MODE_ADD_TO_BOTTOM)) {
241    
242                                    portletIds = ArrayUtil.append(portletIds, portletId);
243                            }
244                            else {
245                                    portletIds = ArrayUtil.append(
246                                            new String[] {portletId}, portletIds);
247                            }
248                    }
249    
250                    return portletIds;
251            }
252    
253            @Override
254            protected void doExportStagedModel(
255                            PortletDataContext portletDataContext, Layout layout)
256                    throws Exception {
257    
258                    Element layoutElement = portletDataContext.getExportDataElement(layout);
259    
260                    populateElementLayoutMetadata(layoutElement, layout);
261    
262                    layoutElement.addAttribute(Constants.ACTION, Constants.ADD);
263    
264                    portletDataContext.setPlid(layout.getPlid());
265    
266                    long parentLayoutId = layout.getParentLayoutId();
267    
268                    if (parentLayoutId != LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
269                            Layout parentLayout = LayoutLocalServiceUtil.fetchLayout(
270                                    layout.getGroupId(), layout.isPrivateLayout(), parentLayoutId);
271    
272                            if (parentLayout != null) {
273                                    StagedModelDataHandlerUtil.exportReferenceStagedModel(
274                                            portletDataContext, layout, parentLayout,
275                                            PortletDataContext.REFERENCE_TYPE_PARENT);
276    
277                                    layoutElement.addAttribute(
278                                            "parent-layout-uuid", parentLayout.getUuid());
279                            }
280                    }
281    
282                    List<LayoutFriendlyURL> layoutFriendlyURLs =
283                            LayoutFriendlyURLLocalServiceUtil.getLayoutFriendlyURLs(
284                                    layout.getPlid());
285    
286                    for (LayoutFriendlyURL layoutFriendlyURL : layoutFriendlyURLs) {
287                            StagedModelDataHandlerUtil.exportReferenceStagedModel(
288                                    portletDataContext, layout, layoutFriendlyURL,
289                                    PortletDataContext.REFERENCE_TYPE_DEPENDENCY);
290                    }
291    
292                    if (layout.isIconImage()) {
293                            exportLayoutIconImage(portletDataContext, layout, layoutElement);
294                    }
295    
296                    if (layout.isTypeArticle()) {
297                            exportJournalArticle(portletDataContext, layout);
298                    }
299                    else if (layout.isTypeLinkToLayout()) {
300                            exportLinkedLayout(portletDataContext, layout, layoutElement);
301                    }
302    
303                    fixExportTypeSettings(layout);
304    
305                    exportTheme(portletDataContext, layout);
306    
307                    portletDataContext.addClassedModel(
308                            layoutElement, ExportImportPathUtil.getModelPath(layout), layout);
309            }
310    
311            @Override
312            protected void doImportStagedModel(
313                            PortletDataContext portletDataContext, Layout layout)
314                    throws Exception {
315    
316                    long groupId = portletDataContext.getGroupId();
317                    long userId = portletDataContext.getUserId(layout.getUserUuid());
318    
319                    Element layoutElement =
320                            portletDataContext.getImportDataStagedModelElement(layout);
321    
322                    String layoutUuid = GetterUtil.getString(
323                            layoutElement.attributeValue("layout-uuid"));
324    
325                    long layoutId = GetterUtil.getInteger(
326                            layoutElement.attributeValue("layout-id"));
327    
328                    long oldLayoutId = layoutId;
329    
330                    boolean privateLayout = portletDataContext.isPrivateLayout();
331    
332                    String action = layoutElement.attributeValue(Constants.ACTION);
333    
334                    if (action.equals(Constants.DELETE)) {
335                            Layout deletingLayout =
336                                    LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
337                                            layoutUuid, groupId, privateLayout);
338    
339                            LayoutLocalServiceUtil.deleteLayout(
340                                    deletingLayout, false,
341                                    ServiceContextThreadLocal.getServiceContext());
342    
343                            return;
344                    }
345    
346                    Map<Long, Layout> layouts =
347                            (Map<Long, Layout>)portletDataContext.getNewPrimaryKeysMap(
348                                    Layout.class + ".layout");
349    
350                    Layout existingLayout = null;
351                    Layout importedLayout = null;
352    
353                    String friendlyURL = layout.getFriendlyURL();
354    
355                    String layoutsImportMode = MapUtil.getString(
356                            portletDataContext.getParameterMap(),
357                            PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE,
358                            PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_MERGE_BY_LAYOUT_UUID);
359    
360                    if (layoutsImportMode.equals(
361                                    PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_ADD_AS_NEW)) {
362    
363                            layoutId = LayoutLocalServiceUtil.getNextLayoutId(
364                                    groupId, privateLayout);
365                            friendlyURL = StringPool.SLASH + layoutId;
366                    }
367                    else if (layoutsImportMode.equals(
368                                            PortletDataHandlerKeys.
369                                                    LAYOUTS_IMPORT_MODE_MERGE_BY_LAYOUT_NAME)) {
370    
371                            Locale locale = LocaleUtil.getSiteDefault();
372    
373                            String localizedName = layout.getName(locale);
374    
375                            List<Layout> previousLayouts = LayoutLocalServiceUtil.getLayouts(
376                                    groupId, privateLayout);
377    
378                            for (Layout curLayout : previousLayouts) {
379                                    if (localizedName.equals(curLayout.getName(locale)) ||
380                                            friendlyURL.equals(curLayout.getFriendlyURL())) {
381    
382                                            existingLayout = curLayout;
383    
384                                            break;
385                                    }
386                            }
387    
388                            if (existingLayout == null) {
389                                    layoutId = LayoutLocalServiceUtil.getNextLayoutId(
390                                            groupId, privateLayout);
391                            }
392                    }
393                    else if (layoutsImportMode.equals(
394                                            PortletDataHandlerKeys.
395                                                    LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE)) {
396    
397                            existingLayout = LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
398                                    layout.getUuid(), groupId, privateLayout);
399    
400                            if (SitesUtil.isLayoutModifiedSinceLastMerge(existingLayout)) {
401                                    layouts.put(oldLayoutId, existingLayout);
402    
403                                    return;
404                            }
405    
406                            LayoutFriendlyURL layoutFriendlyURL =
407                                    LayoutFriendlyURLLocalServiceUtil.fetchFirstLayoutFriendlyURL(
408                                            groupId, privateLayout, friendlyURL);
409    
410                            if ((layoutFriendlyURL != null) && (existingLayout == null)) {
411                                    Layout mergeFailFriendlyURLLayout =
412                                            LayoutLocalServiceUtil.getLayout(
413                                                    layoutFriendlyURL.getPlid());
414    
415                                    SitesUtil.addMergeFailFriendlyURLLayout(
416                                            mergeFailFriendlyURLLayout);
417    
418                                    return;
419                            }
420                    }
421                    else {
422    
423                            // The default behaviour of import mode is
424                            // PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_MERGE_BY_LAYOUT_UUID
425    
426                            existingLayout = LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
427                                    layout.getUuid(), groupId, privateLayout);
428    
429                            if (existingLayout == null) {
430                                    existingLayout =
431                                            LayoutLocalServiceUtil.fetchLayoutByFriendlyURL(
432                                                    groupId, privateLayout, friendlyURL);
433                            }
434    
435                            if (existingLayout == null) {
436                                    layoutId = LayoutLocalServiceUtil.getNextLayoutId(
437                                            groupId, privateLayout);
438                            }
439                    }
440    
441                    if (_log.isDebugEnabled()) {
442                            StringBundler sb = new StringBundler(7);
443    
444                            sb.append("Layout with {groupId=");
445                            sb.append(groupId);
446                            sb.append(",privateLayout=");
447                            sb.append(privateLayout);
448                            sb.append(",layoutId=");
449                            sb.append(layoutId);
450    
451                            if (existingLayout == null) {
452                                    sb.append("} does not exist");
453    
454                                    _log.debug(sb.toString());
455                            }
456                            else {
457                                    sb.append("} exists");
458    
459                                    _log.debug(sb.toString());
460                            }
461                    }
462    
463                    if (existingLayout == null) {
464                            long plid = CounterLocalServiceUtil.increment();
465    
466                            importedLayout = LayoutLocalServiceUtil.createLayout(plid);
467    
468                            if (layoutsImportMode.equals(
469                                            PortletDataHandlerKeys.
470                                                    LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE)) {
471    
472                                    importedLayout.setSourcePrototypeLayoutUuid(layout.getUuid());
473    
474                                    layoutId = LayoutLocalServiceUtil.getNextLayoutId(
475                                            groupId, privateLayout);
476                            }
477                            else {
478                                    importedLayout.setCreateDate(layout.getCreateDate());
479                                    importedLayout.setModifiedDate(layout.getModifiedDate());
480                                    importedLayout.setLayoutPrototypeUuid(
481                                            layout.getLayoutPrototypeUuid());
482                                    importedLayout.setLayoutPrototypeLinkEnabled(
483                                            layout.isLayoutPrototypeLinkEnabled());
484                                    importedLayout.setSourcePrototypeLayoutUuid(
485                                            layout.getSourcePrototypeLayoutUuid());
486                            }
487    
488                            importedLayout.setUuid(layout.getUuid());
489                            importedLayout.setGroupId(groupId);
490                            importedLayout.setUserId(userId);
491                            importedLayout.setPrivateLayout(privateLayout);
492                            importedLayout.setLayoutId(layoutId);
493    
494                            initNewLayoutPermissions(
495                                    portletDataContext.getCompanyId(), groupId, userId, layout,
496                                    importedLayout, privateLayout);
497    
498                            LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
499                                    groupId, privateLayout);
500    
501                            importedLayout.setLayoutSet(layoutSet);
502                    }
503                    else {
504                            importedLayout = existingLayout;
505                    }
506    
507                    portletDataContext.setPlid(importedLayout.getPlid());
508                    portletDataContext.setOldPlid(layout.getPlid());
509    
510                    long parentLayoutId = layout.getParentLayoutId();
511    
512                    String parentLayoutUuid = GetterUtil.getString(
513                            layoutElement.attributeValue("parent-layout-uuid"));
514    
515                    Element parentLayoutElement =
516                            portletDataContext.getReferenceDataElement(
517                                    layout, Layout.class, layout.getGroupId(), parentLayoutUuid);
518    
519                    if ((parentLayoutId != LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) &&
520                            (parentLayoutElement != null)) {
521    
522                            StagedModelDataHandlerUtil.importStagedModel(
523                                    portletDataContext, parentLayoutElement);
524    
525                            Layout importedParentLayout = layouts.get(parentLayoutId);
526    
527                            parentLayoutId = importedParentLayout.getLayoutId();
528                    }
529    
530                    if (_log.isDebugEnabled()) {
531                            StringBundler sb = new StringBundler(4);
532    
533                            sb.append("Importing layout with layout id ");
534                            sb.append(layoutId);
535                            sb.append(" and parent layout id ");
536                            sb.append(parentLayoutId);
537    
538                            _log.debug(sb.toString());
539                    }
540    
541                    importedLayout.setCompanyId(portletDataContext.getCompanyId());
542    
543                    if (layout.getLayoutPrototypeUuid() != null) {
544                            importedLayout.setModifiedDate(new Date());
545                    }
546    
547                    importedLayout.setParentLayoutId(parentLayoutId);
548                    importedLayout.setName(layout.getName());
549                    importedLayout.setTitle(layout.getTitle());
550                    importedLayout.setDescription(layout.getDescription());
551                    importedLayout.setKeywords(layout.getKeywords());
552                    importedLayout.setRobots(layout.getRobots());
553                    importedLayout.setType(layout.getType());
554    
555                    String portletsMergeMode = MapUtil.getString(
556                            portletDataContext.getParameterMap(),
557                            PortletDataHandlerKeys.PORTLETS_MERGE_MODE,
558                            PortletDataHandlerKeys.PORTLETS_MERGE_MODE_REPLACE);
559    
560                    if (layout.isTypeArticle()) {
561                            importJournalArticle(portletDataContext, layout);
562    
563                            updateTypeSettings(importedLayout, layout);
564                    }
565                    else if (layout.isTypePortlet() &&
566                                     Validator.isNotNull(layout.getTypeSettings()) &&
567                                     !portletsMergeMode.equals(
568                                             PortletDataHandlerKeys.PORTLETS_MERGE_MODE_REPLACE)) {
569    
570                            mergePortlets(
571                                    importedLayout, layout.getTypeSettings(), portletsMergeMode);
572                    }
573                    else if (layout.isTypeLinkToLayout()) {
574                            importLinkedLayout(
575                                    portletDataContext, layout, importedLayout, layoutElement,
576                                    layouts);
577                    }
578                    else {
579                            updateTypeSettings(importedLayout, layout);
580                    }
581    
582                    importedLayout.setHidden(layout.isHidden());
583                    importedLayout.setFriendlyURL(
584                            getUniqueFriendlyURL(
585                                    portletDataContext, importedLayout, friendlyURL));
586    
587                    if (layout.getIconImageId() > 0) {
588                            importLayoutIconImage(
589                                    portletDataContext, importedLayout, layoutElement);
590                    }
591                    else if (importedLayout.getIconImageId() > 0) {
592                            ImageLocalServiceUtil.deleteImage(importedLayout.getIconImageId());
593                    }
594    
595                    if (existingLayout == null) {
596                            int priority = _layoutLocalServiceHelper.getNextPriority(
597                                    groupId, privateLayout, parentLayoutId, null, -1);
598    
599                            importedLayout.setPriority(priority);
600                    }
601    
602                    importedLayout.setLayoutPrototypeUuid(layout.getLayoutPrototypeUuid());
603                    importedLayout.setLayoutPrototypeLinkEnabled(
604                            layout.isLayoutPrototypeLinkEnabled());
605    
606                    ServiceContext serviceContext = portletDataContext.createServiceContext(
607                            layout);
608    
609                    importedLayout.setExpandoBridgeAttributes(serviceContext);
610    
611                    StagingUtil.updateLastImportSettings(
612                            layoutElement, importedLayout, portletDataContext);
613    
614                    fixImportTypeSettings(importedLayout);
615    
616                    importTheme(portletDataContext, layout, importedLayout);
617    
618                    LayoutLocalServiceUtil.updateLayout(importedLayout);
619    
620                    LayoutSetLocalServiceUtil.updatePageCount(groupId, privateLayout);
621    
622                    Map<Long, Long> layoutPlids =
623                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
624                                    Layout.class);
625    
626                    layoutPlids.put(layout.getPlid(), importedLayout.getPlid());
627    
628                    layouts.put(oldLayoutId, importedLayout);
629    
630                    importAssets(portletDataContext, layout, importedLayout);
631    
632                    importLayoutFriendlyURLs(portletDataContext, layout);
633    
634                    portletDataContext.importClassedModel(layout, importedLayout);
635            }
636    
637            protected void exportJournalArticle(
638                            PortletDataContext portletDataContext, Layout layout)
639                    throws Exception {
640    
641                    UnicodeProperties typeSettingsProperties =
642                            layout.getTypeSettingsProperties();
643    
644                    String articleId = typeSettingsProperties.getProperty(
645                            "article-id", StringPool.BLANK);
646    
647                    long articleGroupId = layout.getGroupId();
648    
649                    if (Validator.isNull(articleId)) {
650                            if (_log.isWarnEnabled()) {
651                                    _log.warn(
652                                            "No article id found in typeSettings of layout " +
653                                                    layout.getPlid());
654                            }
655                    }
656    
657                    JournalArticle article = null;
658    
659                    try {
660                            article = JournalArticleLocalServiceUtil.getLatestArticle(
661                                    articleGroupId, articleId, WorkflowConstants.STATUS_APPROVED);
662                    }
663                    catch (NoSuchArticleException nsae) {
664                            if (_log.isWarnEnabled()) {
665                                    StringBundler sb = new StringBundler(4);
666    
667                                    sb.append("No approved article found with group id ");
668                                    sb.append(articleGroupId);
669                                    sb.append(" and layout id ");
670                                    sb.append(articleId);
671    
672                                    _log.warn(sb.toString());
673                            }
674                    }
675    
676                    if (article == null) {
677                            return;
678                    }
679    
680                    StagedModelDataHandlerUtil.exportReferenceStagedModel(
681                            portletDataContext, layout, article,
682                            PortletDataContext.REFERENCE_TYPE_EMBEDDED);
683            }
684    
685            protected void exportLayoutIconImage(
686                            PortletDataContext portletDataContext, Layout layout,
687                            Element layoutElement)
688                    throws Exception {
689    
690                    Image image = ImageLocalServiceUtil.getImage(layout.getIconImageId());
691    
692                    if (image != null) {
693                            String iconPath = ExportImportPathUtil.getModelPath(
694                                    portletDataContext.getScopeGroupId(), Image.class.getName(),
695                                    image.getImageId());
696    
697                            Element iconImagePathElement = layoutElement.addElement(
698                                    "icon-image-path");
699    
700                            iconImagePathElement.addText(iconPath);
701    
702                            portletDataContext.addZipEntry(iconPath, image.getTextObj());
703                    }
704            }
705    
706            protected void exportLinkedLayout(
707                            PortletDataContext portletDataContext, Layout layout,
708                            Element layoutElement)
709                    throws Exception {
710    
711                    UnicodeProperties typeSettingsProperties =
712                            layout.getTypeSettingsProperties();
713    
714                    long linkToLayoutId = GetterUtil.getLong(
715                            typeSettingsProperties.getProperty(
716                                    "linkToLayoutId", StringPool.BLANK));
717    
718                    if (linkToLayoutId > 0) {
719                            try {
720                                    Layout linkedToLayout = LayoutLocalServiceUtil.getLayout(
721                                            portletDataContext.getScopeGroupId(),
722                                            layout.isPrivateLayout(), linkToLayoutId);
723    
724                                    StagedModelDataHandlerUtil.exportReferenceStagedModel(
725                                            portletDataContext, layout, linkedToLayout,
726                                            PortletDataContext.REFERENCE_TYPE_STRONG);
727    
728                                    layoutElement.addAttribute(
729                                            "linked-to-layout-uuid", linkedToLayout.getUuid());
730                            }
731                            catch (NoSuchLayoutException nsle) {
732                            }
733                    }
734            }
735    
736            protected void exportTheme(
737                            PortletDataContext portletDataContext, Layout layout)
738                    throws Exception {
739    
740                    boolean exportThemeSettings = MapUtil.getBoolean(
741                            portletDataContext.getParameterMap(),
742                            PortletDataHandlerKeys.THEME_REFERENCE);
743    
744                    if (_log.isDebugEnabled()) {
745                            _log.debug("Export theme settings " + exportThemeSettings);
746                    }
747    
748                    if (exportThemeSettings &&
749                            !portletDataContext.isPerformDirectBinaryImport() &&
750                            !layout.isInheritLookAndFeel()) {
751    
752                            StagedTheme stagedTheme = new StagedThemeImpl(layout.getTheme());
753    
754                            Element layoutElement = portletDataContext.getExportDataElement(
755                                    layout);
756    
757                            portletDataContext.addReferenceElement(
758                                    layout, layoutElement, stagedTheme,
759                                    PortletDataContext.REFERENCE_TYPE_DEPENDENCY, true);
760                    }
761            }
762    
763            protected Object[] extractFriendlyURLInfo(Layout layout) {
764                    if (!layout.isTypeURL()) {
765                            return null;
766                    }
767    
768                    UnicodeProperties typeSettings = layout.getTypeSettingsProperties();
769    
770                    String url = GetterUtil.getString(typeSettings.getProperty("url"));
771    
772                    String friendlyURLPrivateGroupPath =
773                            PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_GROUP_SERVLET_MAPPING;
774                    String friendlyURLPrivateUserPath =
775                            PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING;
776                    String friendlyURLPublicPath =
777                            PropsValues.LAYOUT_FRIENDLY_URL_PUBLIC_SERVLET_MAPPING;
778    
779                    if (!url.startsWith(friendlyURLPrivateGroupPath) &&
780                            !url.startsWith(friendlyURLPrivateUserPath) &&
781                            !url.startsWith(friendlyURLPublicPath)) {
782    
783                            return null;
784                    }
785    
786                    int x = url.indexOf(CharPool.SLASH, 1);
787    
788                    if (x == -1) {
789                            return null;
790                    }
791    
792                    int y = url.indexOf(CharPool.SLASH, x + 1);
793    
794                    if (y == -1) {
795                            return null;
796                    }
797    
798                    return new Object[] {url.substring(x, y), url, x, y};
799            }
800    
801            protected Layout fetchMissingReference(
802                    String uuid, long groupId, boolean privateLayout) {
803    
804                    // Try to fetch the existing layout from the importing group
805    
806                    Layout layout = LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
807                            uuid, groupId, privateLayout);
808    
809                    if (layout != null) {
810                            return layout;
811                    }
812    
813                    try {
814    
815                            // Try to fetch the existing layout from the parent sites
816    
817                            Group originalGroup = GroupLocalServiceUtil.getGroup(groupId);
818    
819                            Group group = originalGroup.getParentGroup();
820    
821                            while (group != null) {
822                                    layout = LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
823                                            uuid, group.getGroupId(), privateLayout);
824    
825                                    if (layout != null) {
826                                            break;
827                                    }
828    
829                                    group = group.getParentGroup();
830                            }
831    
832                            if (layout == null) {
833                                    layout = fetchStagedModelByUuidAndCompanyId(
834                                            uuid, originalGroup.getCompanyId());
835                            }
836    
837                            return layout;
838                    }
839                    catch (Exception e) {
840                            if (_log.isDebugEnabled()) {
841                                    _log.debug(e, e);
842                            }
843                            else if (_log.isWarnEnabled()) {
844                                    _log.warn(
845                                            "Unable to fetch missing reference layout from group " +
846                                                    groupId);
847                            }
848    
849                            return null;
850                    }
851            }
852    
853            protected void fixExportTypeSettings(Layout layout) throws Exception {
854                    Object[] friendlyURLInfo = extractFriendlyURLInfo(layout);
855    
856                    if (friendlyURLInfo == null) {
857                            return;
858                    }
859    
860                    String friendlyURL = (String)friendlyURLInfo[0];
861    
862                    Group group = layout.getGroup();
863    
864                    String groupFriendlyURL = group.getFriendlyURL();
865    
866                    if (!friendlyURL.equals(groupFriendlyURL)) {
867                            return;
868                    }
869    
870                    UnicodeProperties typeSettings = layout.getTypeSettingsProperties();
871    
872                    String url = (String)friendlyURLInfo[1];
873    
874                    int x = (Integer)friendlyURLInfo[2];
875                    int y = (Integer)friendlyURLInfo[3];
876    
877                    typeSettings.setProperty(
878                            "url",
879                            url.substring(0, x) + _SAME_GROUP_FRIENDLY_URL + url.substring(y));
880            }
881    
882            protected void fixImportTypeSettings(Layout layout) throws Exception {
883                    Object[] friendlyURLInfo = extractFriendlyURLInfo(layout);
884    
885                    if (friendlyURLInfo == null) {
886                            return;
887                    }
888    
889                    String friendlyURL = (String)friendlyURLInfo[0];
890    
891                    if (!friendlyURL.equals(_SAME_GROUP_FRIENDLY_URL)) {
892                            return;
893                    }
894    
895                    Group group = layout.getGroup();
896    
897                    UnicodeProperties typeSettings = layout.getTypeSettingsProperties();
898    
899                    String url = (String)friendlyURLInfo[1];
900    
901                    int x = (Integer)friendlyURLInfo[2];
902                    int y = (Integer)friendlyURLInfo[3];
903    
904                    typeSettings.setProperty(
905                            "url",
906                            url.substring(0, x) + group.getFriendlyURL() + url.substring(y));
907            }
908    
909            protected String getUniqueFriendlyURL(
910                    PortletDataContext portletDataContext, Layout existingLayout,
911                    String friendlyURL) {
912    
913                    for (int i = 1;; i++) {
914                            Layout duplicateFriendlyURLLayout =
915                                    LayoutLocalServiceUtil.fetchLayoutByFriendlyURL(
916                                            portletDataContext.getGroupId(),
917                                            portletDataContext.isPrivateLayout(), friendlyURL);
918    
919                            if ((duplicateFriendlyURLLayout == null) ||
920                                    (duplicateFriendlyURLLayout.getPlid() ==
921                                            existingLayout.getPlid())) {
922    
923                                    break;
924                            }
925    
926                            friendlyURL = friendlyURL + i;
927                    }
928    
929                    return friendlyURL;
930            }
931    
932            protected void importAssets(
933                            PortletDataContext portletDataContext, Layout layout,
934                            Layout importedLayout)
935                    throws Exception {
936    
937                    long userId = portletDataContext.getUserId(layout.getUserUuid());
938    
939                    long[] assetCategoryIds = portletDataContext.getAssetCategoryIds(
940                            Layout.class, layout.getPlid());
941                    String[] assetTagNames = portletDataContext.getAssetTagNames(
942                            Layout.class, layout.getPlid());
943    
944                    LayoutLocalServiceUtil.updateAsset(
945                            userId, importedLayout, assetCategoryIds, assetTagNames);
946            }
947    
948            protected void importJournalArticle(
949                            PortletDataContext portletDataContext, Layout layout)
950                    throws Exception {
951    
952                    UnicodeProperties typeSettingsProperties =
953                            layout.getTypeSettingsProperties();
954    
955                    String articleId = typeSettingsProperties.getProperty(
956                            "article-id", StringPool.BLANK);
957    
958                    if (Validator.isNull(articleId)) {
959                            return;
960                    }
961    
962                    List<Element> referenceDataElements =
963                            portletDataContext.getReferenceDataElements(
964                                    layout, JournalArticle.class);
965    
966                    if (!referenceDataElements.isEmpty()) {
967                            StagedModelDataHandlerUtil.importStagedModel(
968                                    portletDataContext, referenceDataElements.get(0));
969                    }
970    
971                    Map<String, String> articleIds =
972                            (Map<String, String>)portletDataContext.getNewPrimaryKeysMap(
973                                    JournalArticle.class + ".articleId");
974    
975                    articleId = MapUtil.getString(articleIds, articleId, articleId);
976    
977                    typeSettingsProperties.setProperty("article-id", articleId);
978    
979                    JournalContentSearchLocalServiceUtil.updateContentSearch(
980                            portletDataContext.getScopeGroupId(), layout.isPrivateLayout(),
981                            layout.getLayoutId(), StringPool.BLANK, articleId, true);
982            }
983    
984            protected void importLayoutFriendlyURLs(
985                            PortletDataContext portletDataContext, Layout layout)
986                    throws Exception {
987    
988                    List<Element> layoutFriendlyURLElements =
989                            portletDataContext.getReferenceDataElements(
990                                    layout, LayoutFriendlyURL.class);
991    
992                    for (Element layoutFriendlyURLElement : layoutFriendlyURLElements) {
993                            String layoutFriendlyURLPath =
994                                    layoutFriendlyURLElement.attributeValue("path");
995    
996                            LayoutFriendlyURL layoutFriendlyURL =
997                                    (LayoutFriendlyURL)portletDataContext.getZipEntryAsObject(
998                                            layoutFriendlyURLPath);
999    
1000                            StagedModelDataHandlerUtil.importStagedModel(
1001                                    portletDataContext, layoutFriendlyURL);
1002                    }
1003            }
1004    
1005            protected void importLayoutIconImage(
1006                            PortletDataContext portletDataContext, Layout importedLayout,
1007                            Element layoutElement)
1008                    throws Exception {
1009    
1010                    String iconImagePath = layoutElement.elementText("icon-image-path");
1011    
1012                    byte[] iconBytes = portletDataContext.getZipEntryAsByteArray(
1013                            iconImagePath);
1014    
1015                    if (ArrayUtil.isNotEmpty(iconBytes)) {
1016                            if (importedLayout.getIconImageId() == 0) {
1017                                    long iconImageId = CounterLocalServiceUtil.increment();
1018    
1019                                    importedLayout.setIconImageId(iconImageId);
1020                            }
1021    
1022                            ImageLocalServiceUtil.updateImage(
1023                                    importedLayout.getIconImageId(), iconBytes);
1024                    }
1025            }
1026    
1027            protected void importLinkedLayout(
1028                            PortletDataContext portletDataContext, Layout layout,
1029                            Layout importedLayout, Element layoutElement,
1030                            Map<Long, Layout> layouts)
1031                    throws Exception {
1032    
1033                    UnicodeProperties typeSettingsProperties =
1034                            layout.getTypeSettingsProperties();
1035    
1036                    long linkToLayoutId = GetterUtil.getLong(
1037                            typeSettingsProperties.getProperty(
1038                                    "linkToLayoutId", StringPool.BLANK));
1039    
1040                    String linkedToLayoutUuid = layoutElement.attributeValue(
1041                            "linked-to-layout-uuid");
1042    
1043                    if (Validator.isNull(linkedToLayoutUuid)) {
1044                            return;
1045                    }
1046    
1047                    if (linkToLayoutId <= 0) {
1048                            updateTypeSettings(importedLayout, layout);
1049    
1050                            return;
1051                    }
1052    
1053                    Element linkedToLayoutElement =
1054                            portletDataContext.getReferenceDataElement(
1055                                    layout, Layout.class, layout.getGroupId(), linkedToLayoutUuid);
1056    
1057                    if (linkedToLayoutElement != null) {
1058                            String linkedToLayoutPath = linkedToLayoutElement.attributeValue(
1059                                    "path");
1060    
1061                            Layout linkedToLayout =
1062                                    (Layout)portletDataContext.getZipEntryAsObject(
1063                                            linkedToLayoutPath);
1064    
1065                            StagedModelDataHandlerUtil.importStagedModel(
1066                                    portletDataContext, linkedToLayout);
1067    
1068                            Layout importedLinkedLayout = layouts.get(linkToLayoutId);
1069    
1070                            typeSettingsProperties.setProperty(
1071                                    "privateLayout",
1072                                    String.valueOf(importedLinkedLayout.isPrivateLayout()));
1073                            typeSettingsProperties.setProperty(
1074                                    "linkToLayoutId",
1075                                    String.valueOf(importedLinkedLayout.getLayoutId()));
1076                    }
1077                    else {
1078                            if (_log.isWarnEnabled()) {
1079                                    StringBundler sb = new StringBundler(6);
1080    
1081                                    sb.append("Unable to link layout with friendly URL ");
1082                                    sb.append(layout.getFriendlyURL());
1083                                    sb.append(" and layout id ");
1084                                    sb.append(layout.getLayoutId());
1085                                    sb.append(" to layout with layout id ");
1086                                    sb.append(linkToLayoutId);
1087    
1088                                    _log.warn(sb.toString());
1089                            }
1090                    }
1091    
1092                    updateTypeSettings(importedLayout, layout);
1093            }
1094    
1095            @Override
1096            protected void importReferenceStagedModels(
1097                    PortletDataContext portletDataContext, Layout layout) {
1098            }
1099    
1100            protected void importTheme(
1101                            PortletDataContext portletDataContext, Layout layout,
1102                            Layout importedLayout)
1103                    throws Exception {
1104    
1105                    boolean importThemeSettings = MapUtil.getBoolean(
1106                            portletDataContext.getParameterMap(),
1107                            PortletDataHandlerKeys.THEME_REFERENCE);
1108    
1109                    if (_log.isDebugEnabled()) {
1110                            _log.debug("Import theme settings " + importThemeSettings);
1111                    }
1112    
1113                    if (importThemeSettings) {
1114                            importedLayout.setColorSchemeId(layout.getColorSchemeId());
1115                            importedLayout.setCss(layout.getCss());
1116                            importedLayout.setThemeId(layout.getThemeId());
1117                            importedLayout.setWapColorSchemeId(layout.getWapColorSchemeId());
1118                            importedLayout.setWapThemeId(layout.getWapThemeId());
1119                    }
1120                    else {
1121                            importedLayout.setColorSchemeId(StringPool.BLANK);
1122                            importedLayout.setCss(StringPool.BLANK);
1123                            importedLayout.setThemeId(StringPool.BLANK);
1124                            importedLayout.setWapColorSchemeId(StringPool.BLANK);
1125                            importedLayout.setWapThemeId(StringPool.BLANK);
1126                    }
1127            }
1128    
1129            protected void initNewLayoutPermissions(
1130                            long companyId, long groupId, long userId, Layout layout,
1131                            Layout importedLayout, boolean privateLayout)
1132                    throws Exception {
1133    
1134                    boolean addGroupPermissions = true;
1135    
1136                    Group group = importedLayout.getGroup();
1137    
1138                    if (privateLayout && group.isUser()) {
1139                            addGroupPermissions = false;
1140                    }
1141    
1142                    boolean addGuestPermissions = false;
1143    
1144                    if (!privateLayout || layout.isTypeControlPanel()) {
1145                            addGuestPermissions = true;
1146                    }
1147    
1148                    ResourceLocalServiceUtil.addResources(
1149                            companyId, groupId, userId, Layout.class.getName(),
1150                            importedLayout.getPlid(), false, addGroupPermissions,
1151                            addGuestPermissions);
1152            }
1153    
1154            protected void mergePortlets(
1155                    Layout layout, String newTypeSettings, String portletsMergeMode) {
1156    
1157                    try {
1158                            UnicodeProperties previousTypeSettingsProperties =
1159                                    layout.getTypeSettingsProperties();
1160    
1161                            LayoutTypePortlet previousLayoutType =
1162                                    (LayoutTypePortlet)layout.getLayoutType();
1163    
1164                            LayoutTemplate previousLayoutTemplate =
1165                                    previousLayoutType.getLayoutTemplate();
1166    
1167                            List<String> previousColumns = previousLayoutTemplate.getColumns();
1168    
1169                            UnicodeProperties newTypeSettingsProperties = new UnicodeProperties(
1170                                    true);
1171    
1172                            newTypeSettingsProperties.load(newTypeSettings);
1173    
1174                            String layoutTemplateId = newTypeSettingsProperties.getProperty(
1175                                    LayoutTypePortletConstants.LAYOUT_TEMPLATE_ID);
1176    
1177                            previousTypeSettingsProperties.setProperty(
1178                                    LayoutTypePortletConstants.LAYOUT_TEMPLATE_ID,
1179                                    layoutTemplateId);
1180    
1181                            String nestedColumnIds = newTypeSettingsProperties.getProperty(
1182                                    LayoutTypePortletConstants.NESTED_COLUMN_IDS);
1183    
1184                            if (Validator.isNotNull(nestedColumnIds)) {
1185                                    previousTypeSettingsProperties.setProperty(
1186                                            LayoutTypePortletConstants.NESTED_COLUMN_IDS,
1187                                            nestedColumnIds);
1188    
1189                                    String[] nestedColumnIdsArray = StringUtil.split(
1190                                            nestedColumnIds);
1191    
1192                                    for (String nestedColumnId : nestedColumnIdsArray) {
1193                                            String nestedColumnValue =
1194                                                    newTypeSettingsProperties.getProperty(nestedColumnId);
1195    
1196                                            previousTypeSettingsProperties.setProperty(
1197                                                    nestedColumnId, nestedColumnValue);
1198                                    }
1199                            }
1200    
1201                            LayoutTemplate newLayoutTemplate =
1202                                    LayoutTemplateLocalServiceUtil.getLayoutTemplate(
1203                                            layoutTemplateId, false, null);
1204    
1205                            String[] newPortletIds = new String[0];
1206    
1207                            for (String columnId : newLayoutTemplate.getColumns()) {
1208                                    String columnValue = newTypeSettingsProperties.getProperty(
1209                                            columnId);
1210    
1211                                    String[] portletIds = StringUtil.split(columnValue);
1212    
1213                                    if (!previousColumns.contains(columnId)) {
1214                                            newPortletIds = ArrayUtil.append(newPortletIds, portletIds);
1215                                    }
1216                                    else {
1217                                            String[] previousPortletIds = StringUtil.split(
1218                                                    previousTypeSettingsProperties.getProperty(columnId));
1219    
1220                                            portletIds = appendPortletIds(
1221                                                    previousPortletIds, portletIds, portletsMergeMode);
1222    
1223                                            previousTypeSettingsProperties.setProperty(
1224                                                    columnId, StringUtil.merge(portletIds));
1225                                    }
1226                            }
1227    
1228                            // Add portlets in non-existent column to the first column
1229    
1230                            String columnId = previousColumns.get(0);
1231    
1232                            String[] portletIds = StringUtil.split(
1233                                    previousTypeSettingsProperties.getProperty(columnId));
1234    
1235                            appendPortletIds(portletIds, newPortletIds, portletsMergeMode);
1236    
1237                            previousTypeSettingsProperties.setProperty(
1238                                    columnId, StringUtil.merge(portletIds));
1239    
1240                            layout.setTypeSettings(previousTypeSettingsProperties.toString());
1241                    }
1242                    catch (IOException ioe) {
1243                            layout.setTypeSettings(newTypeSettings);
1244                    }
1245            }
1246    
1247            protected void populateElementLayoutMetadata(
1248                            Element layoutElement, Layout layout)
1249                    throws Exception {
1250    
1251                    LayoutStagingHandler layoutStagingHandler =
1252                            LayoutStagingUtil.getLayoutStagingHandler(layout);
1253    
1254                    if (layoutStagingHandler != null) {
1255                            LayoutRevision layoutRevision =
1256                                    layoutStagingHandler.getLayoutRevision();
1257    
1258                            if (layoutRevision != null) {
1259                                    layoutElement.addAttribute(
1260                                            "layout-revision-id",
1261                                            String.valueOf(layoutRevision.getLayoutRevisionId()));
1262                                    layoutElement.addAttribute(
1263                                            "layout-branch-id",
1264                                            String.valueOf(layoutRevision.getLayoutBranchId()));
1265    
1266                                    LayoutBranch layoutBranch = layoutRevision.getLayoutBranch();
1267    
1268                                    layoutElement.addAttribute(
1269                                            "layout-branch-name",
1270                                            String.valueOf(layoutBranch.getName()));
1271                            }
1272                    }
1273    
1274                    layoutElement.addAttribute("layout-uuid", layout.getUuid());
1275                    layoutElement.addAttribute(
1276                            "layout-id", String.valueOf(layout.getLayoutId()));
1277                    layoutElement.addAttribute(
1278                            "layout-priority", String.valueOf(layout.getPriority()));
1279    
1280                    String layoutPrototypeUuid = layout.getLayoutPrototypeUuid();
1281    
1282                    if (Validator.isNotNull(layoutPrototypeUuid)) {
1283                            LayoutPrototype layoutPrototype =
1284                                    LayoutPrototypeLocalServiceUtil.
1285                                            getLayoutPrototypeByUuidAndCompanyId(
1286                                                    layoutPrototypeUuid, layout.getCompanyId());
1287    
1288                            layoutElement.addAttribute(
1289                                    "layout-prototype-uuid", layoutPrototypeUuid);
1290                            layoutElement.addAttribute(
1291                                    "layout-prototype-name",
1292                                    layoutPrototype.getName(LocaleUtil.getDefault()));
1293                    }
1294            }
1295    
1296            protected void updateTypeSettings(Layout importedLayout, Layout layout)
1297                    throws PortalException {
1298    
1299                    long groupId = layout.getGroupId();
1300    
1301                    try {
1302                            LayoutTypePortlet importedLayoutType =
1303                                    (LayoutTypePortlet)importedLayout.getLayoutType();
1304    
1305                            List<String> importedPortletIds =
1306                                    importedLayoutType.getPortletIds();
1307    
1308                            layout.setGroupId(importedLayout.getGroupId());
1309    
1310                            LayoutTypePortlet layoutTypePortlet =
1311                                    (LayoutTypePortlet)layout.getLayoutType();
1312    
1313                            importedPortletIds.removeAll(layoutTypePortlet.getPortletIds());
1314    
1315                            if (!importedPortletIds.isEmpty()) {
1316                                    PortletLocalServiceUtil.deletePortlets(
1317                                            importedLayout.getCompanyId(),
1318                                            importedPortletIds.toArray(
1319                                                    new String[importedPortletIds.size()]),
1320                                            importedLayout.getPlid());
1321                            }
1322    
1323                            importedLayout.setTypeSettingsProperties(
1324                                    layoutTypePortlet.getTypeSettingsProperties());
1325                    }
1326                    finally {
1327                            layout.setGroupId(groupId);
1328                    }
1329            }
1330    
1331            private static final String _SAME_GROUP_FRIENDLY_URL =
1332                    "/[$SAME_GROUP_FRIENDLY_URL$]";
1333    
1334            private static Log _log = LogFactoryUtil.getLog(
1335                    LayoutStagedModelDataHandler.class);
1336    
1337            private LayoutLocalServiceHelper _layoutLocalServiceHelper =
1338                    (LayoutLocalServiceHelper)PortalBeanLocatorUtil.locate(
1339                            LayoutLocalServiceHelper.class.getName());
1340    
1341    }