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