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