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