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