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.setUserId(userId);
414 importedLayout.setPrivateLayout(privateLayout);
415 importedLayout.setLayoutId(layoutId);
416
417 initNewLayoutPermissions(
418 portletDataContext.getCompanyId(), groupId, userId, layout,
419 importedLayout, privateLayout);
420
421 LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
422 groupId, privateLayout);
423
424 importedLayout.setLayoutSet(layoutSet);
425 }
426 else {
427 importedLayout = existingLayout;
428 }
429
430 portletDataContext.setPlid(importedLayout.getPlid());
431 portletDataContext.setOldPlid(layout.getPlid());
432
433 newLayoutsMap.put(oldLayoutId, importedLayout);
434
435 long parentLayoutId = layout.getParentLayoutId();
436
437 String parentLayoutUuid = GetterUtil.getString(
438 layoutElement.attributeValue("parent-layout-uuid"));
439
440 Element parentLayoutElement =
441 portletDataContext.getReferenceDataElement(
442 layout, Layout.class, layout.getGroupId(), parentLayoutUuid);
443
444 if ((parentLayoutId != LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) &&
445 (parentLayoutElement != null)) {
446
447 String parentLayoutPath = parentLayoutElement.attributeValue(
448 "path");
449
450 Layout parentLayout =
451 (Layout)portletDataContext.getZipEntryAsObject(
452 parentLayoutPath);
453
454 StagedModelDataHandlerUtil.importStagedModel(
455 portletDataContext, parentLayout);
456
457 Layout importedParentLayout = newLayoutsMap.get(parentLayoutId);
458
459 parentLayoutId = importedParentLayout.getLayoutId();
460 }
461
462 if (_log.isDebugEnabled()) {
463 StringBundler sb = new StringBundler(4);
464
465 sb.append("Importing layout with layout id ");
466 sb.append(layoutId);
467 sb.append(" and parent layout id ");
468 sb.append(parentLayoutId);
469
470 _log.debug(sb.toString());
471 }
472
473 importedLayout.setCompanyId(portletDataContext.getCompanyId());
474 importedLayout.setParentLayoutId(parentLayoutId);
475 importedLayout.setName(layout.getName());
476 importedLayout.setTitle(layout.getTitle());
477 importedLayout.setDescription(layout.getDescription());
478 importedLayout.setKeywords(layout.getKeywords());
479 importedLayout.setRobots(layout.getRobots());
480 importedLayout.setType(layout.getType());
481
482 String portletsMergeMode = MapUtil.getString(
483 portletDataContext.getParameterMap(),
484 PortletDataHandlerKeys.PORTLETS_MERGE_MODE,
485 PortletDataHandlerKeys.PORTLETS_MERGE_MODE_REPLACE);
486
487 if (layout.isTypeArticle()) {
488 importJournalArticle(portletDataContext, layout);
489
490 updateTypeSettings(importedLayout, layout);
491 }
492 else if (layout.isTypePortlet() &&
493 Validator.isNotNull(layout.getTypeSettings()) &&
494 !portletsMergeMode.equals(
495 PortletDataHandlerKeys.PORTLETS_MERGE_MODE_REPLACE)) {
496
497 mergePortlets(
498 importedLayout, layout.getTypeSettings(), portletsMergeMode);
499 }
500 else if (layout.isTypeLinkToLayout()) {
501 importLinkedLayout(
502 portletDataContext, layout, importedLayout, layoutElement,
503 newLayoutsMap);
504 }
505 else {
506 updateTypeSettings(importedLayout, layout);
507 }
508
509 importedLayout.setHidden(layout.isHidden());
510 importedLayout.setFriendlyURL(
511 getUniqueFriendlyURL(
512 portletDataContext, importedLayout, friendlyURL));
513 importedLayout.setIconImage(false);
514
515 if (layout.isIconImage()) {
516 importLayoutIconImage(
517 portletDataContext, importedLayout, layoutElement);
518 }
519 else {
520 ImageLocalServiceUtil.deleteImage(importedLayout.getIconImageId());
521 }
522
523 importedLayout.setPriority(layout.getPriority());
524 importedLayout.setLayoutPrototypeUuid(layout.getLayoutPrototypeUuid());
525 importedLayout.setLayoutPrototypeLinkEnabled(
526 layout.isLayoutPrototypeLinkEnabled());
527
528 StagingUtil.updateLastImportSettings(
529 layoutElement, importedLayout, portletDataContext);
530
531 fixImportTypeSettings(importedLayout);
532
533 importTheme(portletDataContext, layout, importedLayout);
534
535 LayoutLocalServiceUtil.updateLayout(importedLayout);
536
537 LayoutSetLocalServiceUtil.updatePageCount(groupId, privateLayout);
538
539 List<Layout> newLayouts = portletDataContext.getNewLayouts();
540
541 newLayouts.add(importedLayout);
542
543 Map<Long, Long> layoutPlids =
544 (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
545 Layout.class);
546
547 layoutPlids.put(layout.getPlid(), importedLayout.getPlid());
548
549 importLayoutFriendlyURLs(portletDataContext, layout);
550
551 portletDataContext.importClassedModel(layout, importedLayout);
552 }
553
554 protected void exportJournalArticle(
555 PortletDataContext portletDataContext, Layout layout)
556 throws Exception {
557
558 UnicodeProperties typeSettingsProperties =
559 layout.getTypeSettingsProperties();
560
561 String articleId = typeSettingsProperties.getProperty(
562 "article-id", StringPool.BLANK);
563
564 long articleGroupId = layout.getGroupId();
565
566 if (Validator.isNull(articleId)) {
567 if (_log.isWarnEnabled()) {
568 _log.warn(
569 "No article id found in typeSettings of layout " +
570 layout.getPlid());
571 }
572 }
573
574 JournalArticle article = null;
575
576 try {
577 article = JournalArticleLocalServiceUtil.getLatestArticle(
578 articleGroupId, articleId, WorkflowConstants.STATUS_APPROVED);
579 }
580 catch (NoSuchArticleException nsae) {
581 if (_log.isWarnEnabled()) {
582 StringBundler sb = new StringBundler(4);
583
584 sb.append("No approved article found with group id ");
585 sb.append(articleGroupId);
586 sb.append(" and layout id ");
587 sb.append(articleId);
588
589 _log.warn(sb.toString());
590 }
591 }
592
593 if (article == null) {
594 return;
595 }
596
597 StagedModelDataHandlerUtil.exportReferenceStagedModel(
598 portletDataContext, layout, article,
599 PortletDataContext.REFERENCE_TYPE_EMBEDDED);
600 }
601
602 protected void exportLayoutIconImage(
603 PortletDataContext portletDataContext, Layout layout,
604 Element layoutElement)
605 throws Exception {
606
607 Image image = ImageLocalServiceUtil.getImage(layout.getIconImageId());
608
609 if (image != null) {
610 String iconPath = ExportImportPathUtil.getModelPath(
611 portletDataContext.getScopeGroupId(), Image.class.getName(),
612 image.getImageId());
613
614 Element iconImagePathElement = layoutElement.addElement(
615 "icon-image-path");
616
617 iconImagePathElement.addText(iconPath);
618
619 portletDataContext.addZipEntry(iconPath, image.getTextObj());
620 }
621 }
622
623 protected void exportLinkedLayout(
624 PortletDataContext portletDataContext, Layout layout,
625 Element layoutElement)
626 throws Exception {
627
628 UnicodeProperties typeSettingsProperties =
629 layout.getTypeSettingsProperties();
630
631 long linkToLayoutId = GetterUtil.getLong(
632 typeSettingsProperties.getProperty(
633 "linkToLayoutId", StringPool.BLANK));
634
635 if (linkToLayoutId > 0) {
636 try {
637 Layout linkedToLayout = LayoutLocalServiceUtil.getLayout(
638 portletDataContext.getScopeGroupId(),
639 layout.isPrivateLayout(), linkToLayoutId);
640
641 StagedModelDataHandlerUtil.exportReferenceStagedModel(
642 portletDataContext, layout, linkedToLayout,
643 PortletDataContext.REFERENCE_TYPE_STRONG);
644
645 layoutElement.addAttribute(
646 "linked-to-layout-uuid", linkedToLayout.getUuid());
647 }
648 catch (NoSuchLayoutException nsle) {
649 }
650 }
651 }
652
653 protected void exportTheme(
654 PortletDataContext portletDataContext, Layout layout)
655 throws Exception {
656
657 boolean exportThemeSettings = MapUtil.getBoolean(
658 portletDataContext.getParameterMap(),
659 PortletDataHandlerKeys.THEME_REFERENCE);
660
661 if (_log.isDebugEnabled()) {
662 _log.debug("Export theme settings " + exportThemeSettings);
663 }
664
665 if (exportThemeSettings &&
666 !portletDataContext.isPerformDirectBinaryImport() &&
667 !layout.isInheritLookAndFeel()) {
668
669 StagedTheme stagedTheme = new StagedTheme(layout.getTheme());
670
671 Element layoutElement = portletDataContext.getExportDataElement(
672 layout);
673
674 portletDataContext.addReferenceElement(
675 layout, layoutElement, stagedTheme,
676 PortletDataContext.REFERENCE_TYPE_DEPENDENCY, true);
677 }
678 }
679
680 protected Object[] extractFriendlyURLInfo(Layout layout) {
681 if (!layout.isTypeURL()) {
682 return null;
683 }
684
685 UnicodeProperties typeSettings = layout.getTypeSettingsProperties();
686
687 String url = GetterUtil.getString(typeSettings.getProperty("url"));
688
689 String friendlyURLPrivateGroupPath =
690 PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_GROUP_SERVLET_MAPPING;
691 String friendlyURLPrivateUserPath =
692 PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING;
693 String friendlyURLPublicPath =
694 PropsValues.LAYOUT_FRIENDLY_URL_PUBLIC_SERVLET_MAPPING;
695
696 if (!url.startsWith(friendlyURLPrivateGroupPath) &&
697 !url.startsWith(friendlyURLPrivateUserPath) &&
698 !url.startsWith(friendlyURLPublicPath)) {
699
700 return null;
701 }
702
703 int x = url.indexOf(CharPool.SLASH, 1);
704
705 if (x == -1) {
706 return null;
707 }
708
709 int y = url.indexOf(CharPool.SLASH, x + 1);
710
711 if (y == -1) {
712 return null;
713 }
714
715 return new Object[] {url.substring(x, y), url, x, y};
716 }
717
718 protected void fixExportTypeSettings(Layout layout) throws Exception {
719 Object[] friendlyURLInfo = extractFriendlyURLInfo(layout);
720
721 if (friendlyURLInfo == null) {
722 return;
723 }
724
725 String friendlyURL = (String)friendlyURLInfo[0];
726
727 Group group = layout.getGroup();
728
729 String groupFriendlyURL = group.getFriendlyURL();
730
731 if (!friendlyURL.equals(groupFriendlyURL)) {
732 return;
733 }
734
735 UnicodeProperties typeSettings = layout.getTypeSettingsProperties();
736
737 String url = (String)friendlyURLInfo[1];
738
739 int x = (Integer)friendlyURLInfo[2];
740 int y = (Integer)friendlyURLInfo[3];
741
742 typeSettings.setProperty(
743 "url",
744 url.substring(0, x) + LayoutExporter.SAME_GROUP_FRIENDLY_URL +
745 url.substring(y));
746 }
747
748 protected void fixImportTypeSettings(Layout layout) throws Exception {
749 Object[] friendlyURLInfo = extractFriendlyURLInfo(layout);
750
751 if (friendlyURLInfo == null) {
752 return;
753 }
754
755 String friendlyURL = (String)friendlyURLInfo[0];
756
757 if (!friendlyURL.equals(LayoutExporter.SAME_GROUP_FRIENDLY_URL)) {
758 return;
759 }
760
761 Group group = layout.getGroup();
762
763 UnicodeProperties typeSettings = layout.getTypeSettingsProperties();
764
765 String url = (String)friendlyURLInfo[1];
766
767 int x = (Integer)friendlyURLInfo[2];
768 int y = (Integer)friendlyURLInfo[3];
769
770 typeSettings.setProperty(
771 "url",
772 url.substring(0, x) + group.getFriendlyURL() + url.substring(y));
773 }
774
775 protected String getUniqueFriendlyURL(
776 PortletDataContext portletDataContext, Layout existingLayout,
777 String friendlyURL)
778 throws SystemException {
779
780 for (int i = 1;; i++) {
781 Layout duplicateFriendlyURLLayout =
782 LayoutLocalServiceUtil.fetchLayoutByFriendlyURL(
783 portletDataContext.getGroupId(),
784 portletDataContext.isPrivateLayout(), friendlyURL);
785
786 if ((duplicateFriendlyURLLayout == null) ||
787 (duplicateFriendlyURLLayout.getPlid() ==
788 existingLayout.getPlid())) {
789
790 break;
791 }
792
793 friendlyURL = friendlyURL + i;
794 }
795
796 return friendlyURL;
797 }
798
799 protected void importJournalArticle(
800 PortletDataContext portletDataContext, Layout layout)
801 throws Exception {
802
803 UnicodeProperties typeSettingsProperties =
804 layout.getTypeSettingsProperties();
805
806 String articleId = typeSettingsProperties.getProperty(
807 "article-id", StringPool.BLANK);
808
809 if (Validator.isNull(articleId)) {
810 return;
811 }
812
813 List<Element> referenceDataElements =
814 portletDataContext.getReferenceDataElements(
815 layout, JournalArticle.class);
816
817 if (!referenceDataElements.isEmpty()) {
818 StagedModelDataHandlerUtil.importStagedModel(
819 portletDataContext, referenceDataElements.get(0));
820 }
821
822 Map<String, String> articleIds =
823 (Map<String, String>)portletDataContext.getNewPrimaryKeysMap(
824 JournalArticle.class + ".articleId");
825
826 articleId = MapUtil.getString(articleIds, articleId, articleId);
827
828 typeSettingsProperties.setProperty("article-id", articleId);
829
830 JournalContentSearchLocalServiceUtil.updateContentSearch(
831 portletDataContext.getScopeGroupId(), layout.isPrivateLayout(),
832 layout.getLayoutId(), StringPool.BLANK, articleId, true);
833 }
834
835 protected void importLayoutFriendlyURLs(
836 PortletDataContext portletDataContext, Layout layout)
837 throws Exception {
838
839 List<Element> layoutFriendlyURLElements =
840 portletDataContext.getReferenceDataElements(
841 layout, LayoutFriendlyURL.class);
842
843 for (Element layoutFriendlyURLElement : layoutFriendlyURLElements) {
844 String layoutFriendlyURLPath =
845 layoutFriendlyURLElement.attributeValue("path");
846
847 LayoutFriendlyURL layoutFriendlyURL =
848 (LayoutFriendlyURL)portletDataContext.getZipEntryAsObject(
849 layoutFriendlyURLPath);
850
851 StagedModelDataHandlerUtil.importStagedModel(
852 portletDataContext, layoutFriendlyURL);
853 }
854 }
855
856 protected void importLayoutIconImage(
857 PortletDataContext portletDataContext, Layout importedLayout,
858 Element layoutElement)
859 throws Exception {
860
861 String iconImagePath = layoutElement.elementText("icon-image-path");
862
863 byte[] iconBytes = portletDataContext.getZipEntryAsByteArray(
864 iconImagePath);
865
866 if (ArrayUtil.isNotEmpty(iconBytes)) {
867 importedLayout.setIconImage(true);
868
869 if (importedLayout.getIconImageId() == 0) {
870 long iconImageId = CounterLocalServiceUtil.increment();
871
872 importedLayout.setIconImageId(iconImageId);
873 }
874
875 ImageLocalServiceUtil.updateImage(
876 importedLayout.getIconImageId(), iconBytes);
877 }
878 }
879
880 protected void importLinkedLayout(
881 PortletDataContext portletDataContext, Layout layout,
882 Layout importedLayout, Element layoutElement,
883 Map<Long, Layout> newLayoutsMap)
884 throws Exception {
885
886 UnicodeProperties typeSettingsProperties =
887 layout.getTypeSettingsProperties();
888
889 long linkToLayoutId = GetterUtil.getLong(
890 typeSettingsProperties.getProperty(
891 "linkToLayoutId", StringPool.BLANK));
892
893 String linkedToLayoutUuid = layoutElement.attributeValue(
894 "linked-to-layout-uuid");
895
896 if (linkToLayoutId <= 0) {
897 updateTypeSettings(importedLayout, layout);
898
899 return;
900 }
901
902 Element linkedToLayoutElement =
903 portletDataContext.getReferenceDataElement(
904 layout, Layout.class, layout.getGroupId(), linkedToLayoutUuid);
905
906 if (linkedToLayoutElement != null) {
907 String linkedToLayoutPath = linkedToLayoutElement.attributeValue(
908 "path");
909
910 Layout linkedToLayout =
911 (Layout)portletDataContext.getZipEntryAsObject(
912 linkedToLayoutPath);
913
914 StagedModelDataHandlerUtil.importStagedModel(
915 portletDataContext, linkedToLayout);
916
917 Layout importedLinkedLayout = newLayoutsMap.get(linkToLayoutId);
918
919 typeSettingsProperties.setProperty(
920 "privateLayout",
921 String.valueOf(importedLinkedLayout.isPrivateLayout()));
922 typeSettingsProperties.setProperty(
923 "linkToLayoutId",
924 String.valueOf(importedLinkedLayout.getLayoutId()));
925 }
926 else {
927 if (_log.isWarnEnabled()) {
928 StringBundler sb = new StringBundler(6);
929
930 sb.append("Unable to link layout with friendly URL ");
931 sb.append(layout.getFriendlyURL());
932 sb.append(" and layout id ");
933 sb.append(layout.getLayoutId());
934 sb.append(" to layout with layout id ");
935 sb.append(linkToLayoutId);
936
937 _log.warn(sb.toString());
938 }
939 }
940
941 updateTypeSettings(importedLayout, layout);
942 }
943
944 protected void importTheme(
945 PortletDataContext portletDataContext, Layout layout,
946 Layout importedLayout)
947 throws Exception {
948
949 boolean importThemeSettings = MapUtil.getBoolean(
950 portletDataContext.getParameterMap(),
951 PortletDataHandlerKeys.THEME_REFERENCE);
952
953 if (_log.isDebugEnabled()) {
954 _log.debug("Import theme settings " + importThemeSettings);
955 }
956
957 if (importThemeSettings) {
958 importedLayout.setColorSchemeId(layout.getColorSchemeId());
959 importedLayout.setCss(layout.getCss());
960 importedLayout.setThemeId(layout.getThemeId());
961 importedLayout.setWapColorSchemeId(layout.getWapColorSchemeId());
962 importedLayout.setWapThemeId(layout.getWapThemeId());
963 }
964 else {
965 importedLayout.setColorSchemeId(StringPool.BLANK);
966 importedLayout.setCss(StringPool.BLANK);
967 importedLayout.setThemeId(StringPool.BLANK);
968 importedLayout.setWapColorSchemeId(StringPool.BLANK);
969 importedLayout.setWapThemeId(StringPool.BLANK);
970 }
971 }
972
973 protected void initNewLayoutPermissions(
974 long companyId, long groupId, long userId, Layout layout,
975 Layout importedLayout, boolean privateLayout)
976 throws Exception {
977
978 boolean addGroupPermissions = true;
979
980 Group group = importedLayout.getGroup();
981
982 if (privateLayout && group.isUser()) {
983 addGroupPermissions = false;
984 }
985
986 boolean addGuestPermissions = false;
987
988 if (!privateLayout || layout.isTypeControlPanel()) {
989 addGuestPermissions = true;
990 }
991
992 ResourceLocalServiceUtil.addResources(
993 companyId, groupId, userId, Layout.class.getName(),
994 importedLayout.getPlid(), false, addGroupPermissions,
995 addGuestPermissions);
996 }
997
998 protected void mergePortlets(
999 Layout layout, String newTypeSettings, String portletsMergeMode) {
1000
1001 try {
1002 UnicodeProperties previousTypeSettingsProperties =
1003 layout.getTypeSettingsProperties();
1004
1005 LayoutTypePortlet previousLayoutType =
1006 (LayoutTypePortlet)layout.getLayoutType();
1007
1008 LayoutTemplate previousLayoutTemplate =
1009 previousLayoutType.getLayoutTemplate();
1010
1011 List<String> previousColumns = previousLayoutTemplate.getColumns();
1012
1013 UnicodeProperties newTypeSettingsProperties = new UnicodeProperties(
1014 true);
1015
1016 newTypeSettingsProperties.load(newTypeSettings);
1017
1018 String layoutTemplateId = newTypeSettingsProperties.getProperty(
1019 LayoutTypePortletConstants.LAYOUT_TEMPLATE_ID);
1020
1021 previousTypeSettingsProperties.setProperty(
1022 LayoutTypePortletConstants.LAYOUT_TEMPLATE_ID,
1023 layoutTemplateId);
1024
1025 String nestedColumnIds = newTypeSettingsProperties.getProperty(
1026 LayoutTypePortletConstants.NESTED_COLUMN_IDS);
1027
1028 if (Validator.isNotNull(nestedColumnIds)) {
1029 previousTypeSettingsProperties.setProperty(
1030 LayoutTypePortletConstants.NESTED_COLUMN_IDS,
1031 nestedColumnIds);
1032
1033 String[] nestedColumnIdsArray = StringUtil.split(
1034 nestedColumnIds);
1035
1036 for (String nestedColumnId : nestedColumnIdsArray) {
1037 String nestedColumnValue =
1038 newTypeSettingsProperties.getProperty(nestedColumnId);
1039
1040 previousTypeSettingsProperties.setProperty(
1041 nestedColumnId, nestedColumnValue);
1042 }
1043 }
1044
1045 LayoutTemplate newLayoutTemplate =
1046 LayoutTemplateLocalServiceUtil.getLayoutTemplate(
1047 layoutTemplateId, false, null);
1048
1049 String[] newPortletIds = new String[0];
1050
1051 for (String columnId : newLayoutTemplate.getColumns()) {
1052 String columnValue = newTypeSettingsProperties.getProperty(
1053 columnId);
1054
1055 String[] portletIds = StringUtil.split(columnValue);
1056
1057 if (!previousColumns.contains(columnId)) {
1058 newPortletIds = ArrayUtil.append(newPortletIds, portletIds);
1059 }
1060 else {
1061 String[] previousPortletIds = StringUtil.split(
1062 previousTypeSettingsProperties.getProperty(columnId));
1063
1064 portletIds = appendPortletIds(
1065 previousPortletIds, portletIds, portletsMergeMode);
1066
1067 previousTypeSettingsProperties.setProperty(
1068 columnId, StringUtil.merge(portletIds));
1069 }
1070 }
1071
1072
1073
1074 String columnId = previousColumns.get(0);
1075
1076 String[] portletIds = StringUtil.split(
1077 previousTypeSettingsProperties.getProperty(columnId));
1078
1079 appendPortletIds(portletIds, newPortletIds, portletsMergeMode);
1080
1081 previousTypeSettingsProperties.setProperty(
1082 columnId, StringUtil.merge(portletIds));
1083
1084 layout.setTypeSettings(previousTypeSettingsProperties.toString());
1085 }
1086 catch (IOException ioe) {
1087 layout.setTypeSettings(newTypeSettings);
1088 }
1089 }
1090
1091 protected void populateElementLayoutMetadata(
1092 Element layoutElement, Layout layout, LayoutRevision layoutRevision)
1093 throws Exception {
1094
1095 if (layoutRevision != null) {
1096 layoutElement.addAttribute(
1097 "layout-revision-id",
1098 String.valueOf(layoutRevision.getLayoutRevisionId()));
1099 layoutElement.addAttribute(
1100 "layout-branch-id",
1101 String.valueOf(layoutRevision.getLayoutBranchId()));
1102
1103 LayoutBranch layoutBranch = layoutRevision.getLayoutBranch();
1104
1105 layoutElement.addAttribute(
1106 "layout-branch-name", String.valueOf(layoutBranch.getName()));
1107 }
1108
1109 layoutElement.addAttribute("layout-uuid", layout.getUuid());
1110 layoutElement.addAttribute(
1111 "layout-id", String.valueOf(layout.getLayoutId()));
1112
1113 String layoutPrototypeUuid = layout.getLayoutPrototypeUuid();
1114
1115 if (Validator.isNotNull(layoutPrototypeUuid)) {
1116 LayoutPrototype layoutPrototype =
1117 LayoutPrototypeLocalServiceUtil.
1118 getLayoutPrototypeByUuidAndCompanyId(
1119 layoutPrototypeUuid, layout.getCompanyId());
1120
1121 layoutElement.addAttribute(
1122 "layout-prototype-uuid", layoutPrototypeUuid);
1123 layoutElement.addAttribute(
1124 "layout-prototype-name",
1125 layoutPrototype.getName(LocaleUtil.getDefault()));
1126 }
1127 }
1128
1129 protected void updateTypeSettings(Layout importedLayout, Layout layout)
1130 throws PortalException, SystemException {
1131
1132 long groupId = layout.getGroupId();
1133
1134 try {
1135 LayoutTypePortlet importedLayoutType =
1136 (LayoutTypePortlet)importedLayout.getLayoutType();
1137
1138 List<String> importedPortletIds =
1139 importedLayoutType.getPortletIds();
1140
1141 layout.setGroupId(importedLayout.getGroupId());
1142
1143 LayoutTypePortlet layoutType =
1144 (LayoutTypePortlet)layout.getLayoutType();
1145
1146 importedPortletIds.removeAll(layoutType.getPortletIds());
1147
1148 if (!importedPortletIds.isEmpty()) {
1149 PortletLocalServiceUtil.deletePortlets(
1150 importedLayout.getCompanyId(),
1151 importedPortletIds.toArray(
1152 new String[importedPortletIds.size()]),
1153 importedLayout.getPlid());
1154 }
1155
1156 importedLayout.setTypeSettings(layout.getTypeSettings());
1157 }
1158 finally {
1159 layout.setGroupId(groupId);
1160 }
1161 }
1162
1163 private static Log _log = LogFactoryUtil.getLog(
1164 LayoutStagedModelDataHandler.class);
1165
1166 }