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.bean.PortalBeanLocatorUtil;
020 import com.liferay.portal.kernel.exception.PortalException;
021 import com.liferay.portal.kernel.exception.SystemException;
022 import com.liferay.portal.kernel.json.JSONFactoryUtil;
023 import com.liferay.portal.kernel.json.JSONObject;
024 import com.liferay.portal.kernel.lar.BaseStagedModelDataHandler;
025 import com.liferay.portal.kernel.lar.ExportImportPathUtil;
026 import com.liferay.portal.kernel.lar.PortletDataContext;
027 import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
028 import com.liferay.portal.kernel.lar.StagedModelDataHandlerUtil;
029 import com.liferay.portal.kernel.log.Log;
030 import com.liferay.portal.kernel.log.LogFactoryUtil;
031 import com.liferay.portal.kernel.staging.LayoutStagingUtil;
032 import com.liferay.portal.kernel.staging.StagingUtil;
033 import com.liferay.portal.kernel.util.ArrayUtil;
034 import com.liferay.portal.kernel.util.CharPool;
035 import com.liferay.portal.kernel.util.Constants;
036 import com.liferay.portal.kernel.util.GetterUtil;
037 import com.liferay.portal.kernel.util.ListUtil;
038 import com.liferay.portal.kernel.util.LocaleUtil;
039 import com.liferay.portal.kernel.util.MapUtil;
040 import com.liferay.portal.kernel.util.StringBundler;
041 import com.liferay.portal.kernel.util.StringPool;
042 import com.liferay.portal.kernel.util.StringUtil;
043 import com.liferay.portal.kernel.util.UnicodeProperties;
044 import com.liferay.portal.kernel.util.Validator;
045 import com.liferay.portal.kernel.workflow.WorkflowConstants;
046 import com.liferay.portal.kernel.xml.Element;
047 import com.liferay.portal.lar.LayoutExporter;
048 import com.liferay.portal.lar.LayoutImporter;
049 import com.liferay.portal.model.Group;
050 import com.liferay.portal.model.Image;
051 import com.liferay.portal.model.Layout;
052 import com.liferay.portal.model.LayoutBranch;
053 import com.liferay.portal.model.LayoutConstants;
054 import com.liferay.portal.model.LayoutFriendlyURL;
055 import com.liferay.portal.model.LayoutPrototype;
056 import com.liferay.portal.model.LayoutRevision;
057 import com.liferay.portal.model.LayoutSet;
058 import com.liferay.portal.model.LayoutStagingHandler;
059 import com.liferay.portal.model.LayoutTemplate;
060 import com.liferay.portal.model.LayoutTypePortlet;
061 import com.liferay.portal.model.LayoutTypePortletConstants;
062 import com.liferay.portal.service.ImageLocalServiceUtil;
063 import com.liferay.portal.service.LayoutFriendlyURLLocalServiceUtil;
064 import com.liferay.portal.service.LayoutLocalServiceUtil;
065 import com.liferay.portal.service.LayoutPrototypeLocalServiceUtil;
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.service.impl.LayoutLocalServiceHelper;
073 import com.liferay.portal.util.PropsValues;
074 import com.liferay.portlet.journal.NoSuchArticleException;
075 import com.liferay.portlet.journal.model.JournalArticle;
076 import com.liferay.portlet.journal.service.JournalArticleLocalServiceUtil;
077 import com.liferay.portlet.journal.service.JournalContentSearchLocalServiceUtil;
078 import com.liferay.portlet.sites.util.SitesUtil;
079
080 import java.io.IOException;
081
082 import java.util.ArrayList;
083 import java.util.Date;
084 import java.util.List;
085 import java.util.Locale;
086 import java.util.Map;
087
088
091 public class LayoutStagedModelDataHandler
092 extends BaseStagedModelDataHandler<Layout> {
093
094 public static final String[] CLASS_NAMES = {Layout.class.getName()};
095
096 @Override
097 public void deleteStagedModel(
098 String uuid, long groupId, String className, String extraData)
099 throws PortalException, SystemException {
100
101 JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject(
102 extraData);
103
104 boolean privateLayout = extraDataJSONObject.getBoolean("privateLayout");
105
106 Layout layout = LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
107 uuid, groupId, privateLayout);
108
109 if (layout != null) {
110 LayoutLocalServiceUtil.deleteLayout(
111 layout, true, new ServiceContext());
112 }
113 }
114
115 @Override
116 public String[] getClassNames() {
117 return CLASS_NAMES;
118 }
119
120 @Override
121 public String getDisplayName(Layout layout) {
122 return layout.getNameCurrentValue();
123 }
124
125 protected String[] appendPortletIds(
126 String[] portletIds, String[] newPortletIds, String portletsMergeMode) {
127
128 for (String portletId : newPortletIds) {
129 if (ArrayUtil.contains(portletIds, portletId)) {
130 continue;
131 }
132
133 if (portletsMergeMode.equals(
134 PortletDataHandlerKeys.PORTLETS_MERGE_MODE_ADD_TO_BOTTOM)) {
135
136 portletIds = ArrayUtil.append(portletIds, portletId);
137 }
138 else {
139 portletIds = ArrayUtil.append(
140 new String[] {portletId}, portletIds);
141 }
142 }
143
144 return portletIds;
145 }
146
147 protected void deleteMissingLayoutFriendlyURLs(
148 PortletDataContext portletDataContext, Layout layout)
149 throws SystemException {
150
151 Map<Long, Long> layoutFriendlyURLIds =
152 (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
153 LayoutFriendlyURL.class);
154
155 List<LayoutFriendlyURL> layoutFriendlyURLs =
156 LayoutFriendlyURLLocalServiceUtil.getLayoutFriendlyURLs(
157 layout.getPlid());
158
159 for (LayoutFriendlyURL layoutFriendlyURL : layoutFriendlyURLs) {
160 if (!layoutFriendlyURLIds.containsValue(
161 layoutFriendlyURL.getLayoutFriendlyURLId())) {
162
163 LayoutFriendlyURLLocalServiceUtil.deleteLayoutFriendlyURL(
164 layoutFriendlyURL);
165 }
166 }
167 }
168
169 @Override
170 protected void doExportStagedModel(
171 PortletDataContext portletDataContext, Layout layout)
172 throws Exception {
173
174 Element layoutElement = portletDataContext.getExportDataElement(layout);
175
176 populateElementLayoutMetadata(layoutElement, layout);
177
178 layoutElement.addAttribute("action", Constants.ADD);
179
180 portletDataContext.setPlid(layout.getPlid());
181
182 long parentLayoutId = layout.getParentLayoutId();
183
184 if (parentLayoutId != LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
185 Layout parentLayout = LayoutLocalServiceUtil.fetchLayout(
186 layout.getGroupId(), layout.isPrivateLayout(), parentLayoutId);
187
188 if (parentLayout != null) {
189 StagedModelDataHandlerUtil.exportReferenceStagedModel(
190 portletDataContext, layout, parentLayout,
191 PortletDataContext.REFERENCE_TYPE_PARENT);
192
193 layoutElement.addAttribute(
194 "parent-layout-uuid", parentLayout.getUuid());
195 }
196 }
197
198 List<LayoutFriendlyURL> layoutFriendlyURLs =
199 LayoutFriendlyURLLocalServiceUtil.getLayoutFriendlyURLs(
200 layout.getPlid());
201
202 for (LayoutFriendlyURL layoutFriendlyURL : layoutFriendlyURLs) {
203 StagedModelDataHandlerUtil.exportReferenceStagedModel(
204 portletDataContext, layout, layoutFriendlyURL,
205 PortletDataContext.REFERENCE_TYPE_DEPENDENCY);
206 }
207
208 if (layout.isIconImage()) {
209 exportLayoutIconImage(portletDataContext, layout, layoutElement);
210 }
211
212 if (layout.isTypeArticle()) {
213 exportJournalArticle(portletDataContext, layout);
214 }
215 else if (layout.isTypeLinkToLayout()) {
216 exportLinkedLayout(portletDataContext, layout, layoutElement);
217 }
218
219 fixExportTypeSettings(layout);
220
221 exportTheme(portletDataContext, layout);
222
223 portletDataContext.addClassedModel(
224 layoutElement, ExportImportPathUtil.getModelPath(layout), layout);
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.setUserId(userId);
413 importedLayout.setPrivateLayout(privateLayout);
414 importedLayout.setLayoutId(layoutId);
415
416 initNewLayoutPermissions(
417 portletDataContext.getCompanyId(), groupId, userId, layout,
418 importedLayout, privateLayout);
419
420 LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
421 groupId, privateLayout);
422
423 importedLayout.setLayoutSet(layoutSet);
424 }
425 else {
426 importedLayout = existingLayout;
427 }
428
429 portletDataContext.setPlid(importedLayout.getPlid());
430 portletDataContext.setOldPlid(layout.getPlid());
431
432 newLayoutsMap.put(oldLayoutId, importedLayout);
433
434 long parentLayoutId = layout.getParentLayoutId();
435
436 String parentLayoutUuid = GetterUtil.getString(
437 layoutElement.attributeValue("parent-layout-uuid"));
438
439 Element parentLayoutElement =
440 portletDataContext.getReferenceDataElement(
441 layout, Layout.class, layout.getGroupId(), parentLayoutUuid);
442
443 if ((parentLayoutId != LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) &&
444 (parentLayoutElement != null)) {
445
446 String parentLayoutPath = parentLayoutElement.attributeValue(
447 "path");
448
449 Layout parentLayout =
450 (Layout)portletDataContext.getZipEntryAsObject(
451 parentLayoutPath);
452
453 StagedModelDataHandlerUtil.importStagedModel(
454 portletDataContext, parentLayout);
455
456 Layout importedParentLayout = newLayoutsMap.get(parentLayoutId);
457
458 parentLayoutId = importedParentLayout.getLayoutId();
459 }
460
461 if (_log.isDebugEnabled()) {
462 StringBundler sb = new StringBundler(4);
463
464 sb.append("Importing layout with layout id ");
465 sb.append(layoutId);
466 sb.append(" and parent layout id ");
467 sb.append(parentLayoutId);
468
469 _log.debug(sb.toString());
470 }
471
472 importedLayout.setCompanyId(portletDataContext.getCompanyId());
473
474 if (layout.getLayoutPrototypeUuid() != null) {
475 importedLayout.setModifiedDate(new Date());
476 }
477
478 importedLayout.setParentLayoutId(parentLayoutId);
479 importedLayout.setName(layout.getName());
480 importedLayout.setTitle(layout.getTitle());
481 importedLayout.setDescription(layout.getDescription());
482 importedLayout.setKeywords(layout.getKeywords());
483 importedLayout.setRobots(layout.getRobots());
484 importedLayout.setType(layout.getType());
485
486 String portletsMergeMode = MapUtil.getString(
487 portletDataContext.getParameterMap(),
488 PortletDataHandlerKeys.PORTLETS_MERGE_MODE,
489 PortletDataHandlerKeys.PORTLETS_MERGE_MODE_REPLACE);
490
491 if (layout.isTypeArticle()) {
492 importJournalArticle(portletDataContext, layout);
493
494 updateTypeSettings(portletDataContext, importedLayout, layout);
495 }
496 else if (layout.isTypePortlet() &&
497 Validator.isNotNull(layout.getTypeSettings()) &&
498 !portletsMergeMode.equals(
499 PortletDataHandlerKeys.PORTLETS_MERGE_MODE_REPLACE)) {
500
501 mergePortlets(
502 importedLayout, layout.getTypeSettings(), portletsMergeMode);
503 }
504 else if (layout.isTypeLinkToLayout()) {
505 importLinkedLayout(
506 portletDataContext, layout, importedLayout, layoutElement,
507 newLayoutsMap);
508 }
509 else {
510 updateTypeSettings(portletDataContext, importedLayout, layout);
511 }
512
513 importedLayout.setHidden(layout.isHidden());
514 importedLayout.setFriendlyURL(
515 getUniqueFriendlyURL(
516 portletDataContext, importedLayout, friendlyURL));
517 importedLayout.setIconImage(false);
518
519 if (layout.isIconImage()) {
520 importLayoutIconImage(
521 portletDataContext, importedLayout, layoutElement);
522 }
523 else {
524 ImageLocalServiceUtil.deleteImage(importedLayout.getIconImageId());
525 }
526
527 if (existingLayout == null) {
528 int priority = _layoutLocalServiceHelper.getNextPriority(
529 groupId, privateLayout, parentLayoutId, null, -1);
530
531 importedLayout.setPriority(priority);
532 }
533
534 importedLayout.setLayoutPrototypeUuid(layout.getLayoutPrototypeUuid());
535 importedLayout.setLayoutPrototypeLinkEnabled(
536 layout.isLayoutPrototypeLinkEnabled());
537
538 ServiceContext serviceContext = portletDataContext.createServiceContext(
539 layout);
540
541 importedLayout.setExpandoBridgeAttributes(serviceContext);
542
543 StagingUtil.updateLastImportSettings(
544 layoutElement, importedLayout, portletDataContext);
545
546 fixImportTypeSettings(importedLayout);
547
548 importTheme(portletDataContext, layout, 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, importedLayout);
565
566 portletDataContext.importClassedModel(layout, importedLayout);
567 }
568
569 protected void exportJournalArticle(
570 PortletDataContext portletDataContext, Layout layout)
571 throws Exception {
572
573 UnicodeProperties typeSettingsProperties =
574 layout.getTypeSettingsProperties();
575
576 String articleId = typeSettingsProperties.getProperty(
577 "article-id", StringPool.BLANK);
578
579 long articleGroupId = layout.getGroupId();
580
581 if (Validator.isNull(articleId)) {
582 if (_log.isWarnEnabled()) {
583 _log.warn(
584 "No article id found in typeSettings of layout " +
585 layout.getPlid());
586 }
587 }
588
589 JournalArticle article = null;
590
591 try {
592 article = JournalArticleLocalServiceUtil.getLatestArticle(
593 articleGroupId, articleId, WorkflowConstants.STATUS_APPROVED);
594 }
595 catch (NoSuchArticleException nsae) {
596 if (_log.isWarnEnabled()) {
597 StringBundler sb = new StringBundler(4);
598
599 sb.append("No approved article found with group id ");
600 sb.append(articleGroupId);
601 sb.append(" and layout id ");
602 sb.append(articleId);
603
604 _log.warn(sb.toString());
605 }
606 }
607
608 if (article == null) {
609 return;
610 }
611
612 StagedModelDataHandlerUtil.exportReferenceStagedModel(
613 portletDataContext, layout, article,
614 PortletDataContext.REFERENCE_TYPE_EMBEDDED);
615 }
616
617 protected void exportLayoutIconImage(
618 PortletDataContext portletDataContext, Layout layout,
619 Element layoutElement)
620 throws Exception {
621
622 Image image = ImageLocalServiceUtil.getImage(layout.getIconImageId());
623
624 if (image != null) {
625 String iconPath = ExportImportPathUtil.getModelPath(
626 portletDataContext.getScopeGroupId(), Image.class.getName(),
627 image.getImageId());
628
629 Element iconImagePathElement = layoutElement.addElement(
630 "icon-image-path");
631
632 iconImagePathElement.addText(iconPath);
633
634 portletDataContext.addZipEntry(iconPath, image.getTextObj());
635 }
636 }
637
638 protected void exportLinkedLayout(
639 PortletDataContext portletDataContext, Layout layout,
640 Element layoutElement)
641 throws Exception {
642
643 UnicodeProperties typeSettingsProperties =
644 layout.getTypeSettingsProperties();
645
646 long linkToLayoutId = GetterUtil.getLong(
647 typeSettingsProperties.getProperty(
648 "linkToLayoutId", StringPool.BLANK));
649
650 if (linkToLayoutId > 0) {
651 try {
652 Layout linkedToLayout = LayoutLocalServiceUtil.getLayout(
653 portletDataContext.getScopeGroupId(),
654 layout.isPrivateLayout(), linkToLayoutId);
655
656 StagedModelDataHandlerUtil.exportReferenceStagedModel(
657 portletDataContext, layout, linkedToLayout,
658 PortletDataContext.REFERENCE_TYPE_STRONG);
659
660 layoutElement.addAttribute(
661 "linked-to-layout-uuid", linkedToLayout.getUuid());
662 }
663 catch (NoSuchLayoutException nsle) {
664 }
665 }
666 }
667
668 protected void exportTheme(
669 PortletDataContext portletDataContext, Layout layout)
670 throws Exception {
671
672 boolean exportThemeSettings = MapUtil.getBoolean(
673 portletDataContext.getParameterMap(),
674 PortletDataHandlerKeys.THEME_REFERENCE);
675
676 if (_log.isDebugEnabled()) {
677 _log.debug("Export theme settings " + exportThemeSettings);
678 }
679
680 if (exportThemeSettings &&
681 !portletDataContext.isPerformDirectBinaryImport() &&
682 !layout.isInheritLookAndFeel()) {
683
684 StagedTheme stagedTheme = new StagedTheme(layout.getTheme());
685
686 Element layoutElement = portletDataContext.getExportDataElement(
687 layout);
688
689 portletDataContext.addReferenceElement(
690 layout, layoutElement, stagedTheme,
691 PortletDataContext.REFERENCE_TYPE_DEPENDENCY, true);
692 }
693 }
694
695 protected Object[] extractFriendlyURLInfo(Layout layout) {
696 if (!layout.isTypeURL()) {
697 return null;
698 }
699
700 UnicodeProperties typeSettings = layout.getTypeSettingsProperties();
701
702 String url = GetterUtil.getString(typeSettings.getProperty("url"));
703
704 String friendlyURLPrivateGroupPath =
705 PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_GROUP_SERVLET_MAPPING;
706 String friendlyURLPrivateUserPath =
707 PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING;
708 String friendlyURLPublicPath =
709 PropsValues.LAYOUT_FRIENDLY_URL_PUBLIC_SERVLET_MAPPING;
710
711 if (!url.startsWith(friendlyURLPrivateGroupPath) &&
712 !url.startsWith(friendlyURLPrivateUserPath) &&
713 !url.startsWith(friendlyURLPublicPath)) {
714
715 return null;
716 }
717
718 int x = url.indexOf(CharPool.SLASH, 1);
719
720 if (x == -1) {
721 return null;
722 }
723
724 int y = url.indexOf(CharPool.SLASH, x + 1);
725
726 if (y == -1) {
727 return null;
728 }
729
730 return new Object[] {url.substring(x, y), url, x, y};
731 }
732
733 protected void fixExportTypeSettings(Layout layout) throws Exception {
734 Object[] friendlyURLInfo = extractFriendlyURLInfo(layout);
735
736 if (friendlyURLInfo == null) {
737 return;
738 }
739
740 String friendlyURL = (String)friendlyURLInfo[0];
741
742 Group group = layout.getGroup();
743
744 String groupFriendlyURL = group.getFriendlyURL();
745
746 if (!friendlyURL.equals(groupFriendlyURL)) {
747 return;
748 }
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) + LayoutExporter.SAME_GROUP_FRIENDLY_URL +
760 url.substring(y));
761 }
762
763 protected void fixImportTypeSettings(Layout layout) throws Exception {
764 Object[] friendlyURLInfo = extractFriendlyURLInfo(layout);
765
766 if (friendlyURLInfo == null) {
767 return;
768 }
769
770 String friendlyURL = (String)friendlyURLInfo[0];
771
772 if (!friendlyURL.equals(LayoutExporter.SAME_GROUP_FRIENDLY_URL)) {
773 return;
774 }
775
776 Group group = layout.getGroup();
777
778 UnicodeProperties typeSettings = layout.getTypeSettingsProperties();
779
780 String url = (String)friendlyURLInfo[1];
781
782 int x = (Integer)friendlyURLInfo[2];
783 int y = (Integer)friendlyURLInfo[3];
784
785 typeSettings.setProperty(
786 "url",
787 url.substring(0, x) + group.getFriendlyURL() + url.substring(y));
788 }
789
790 protected String getUniqueFriendlyURL(
791 PortletDataContext portletDataContext, Layout existingLayout,
792 String friendlyURL)
793 throws SystemException {
794
795 for (int i = 1;; i++) {
796 Layout duplicateFriendlyURLLayout =
797 LayoutLocalServiceUtil.fetchLayoutByFriendlyURL(
798 portletDataContext.getGroupId(),
799 portletDataContext.isPrivateLayout(), friendlyURL);
800
801 if ((duplicateFriendlyURLLayout == null) ||
802 (duplicateFriendlyURLLayout.getPlid() ==
803 existingLayout.getPlid())) {
804
805 break;
806 }
807
808 friendlyURL = friendlyURL + i;
809 }
810
811 return friendlyURL;
812 }
813
814 protected void importJournalArticle(
815 PortletDataContext portletDataContext, Layout layout)
816 throws Exception {
817
818 UnicodeProperties typeSettingsProperties =
819 layout.getTypeSettingsProperties();
820
821 String articleId = typeSettingsProperties.getProperty(
822 "article-id", StringPool.BLANK);
823
824 if (Validator.isNull(articleId)) {
825 return;
826 }
827
828 List<Element> referenceDataElements =
829 portletDataContext.getReferenceDataElements(
830 layout, JournalArticle.class);
831
832 if (!referenceDataElements.isEmpty()) {
833 StagedModelDataHandlerUtil.importStagedModel(
834 portletDataContext, referenceDataElements.get(0));
835 }
836
837 Map<String, String> articleIds =
838 (Map<String, String>)portletDataContext.getNewPrimaryKeysMap(
839 JournalArticle.class + ".articleId");
840
841 articleId = MapUtil.getString(articleIds, articleId, articleId);
842
843 typeSettingsProperties.setProperty("article-id", articleId);
844
845 JournalContentSearchLocalServiceUtil.updateContentSearch(
846 portletDataContext.getScopeGroupId(), layout.isPrivateLayout(),
847 layout.getLayoutId(), StringPool.BLANK, articleId, true);
848 }
849
850 protected void importLayoutFriendlyURLs(
851 PortletDataContext portletDataContext, Layout layout,
852 Layout importedLayout)
853 throws Exception {
854
855 List<Element> layoutFriendlyURLElements =
856 portletDataContext.getReferenceDataElements(
857 layout, LayoutFriendlyURL.class);
858
859 for (Element layoutFriendlyURLElement : layoutFriendlyURLElements) {
860 String layoutFriendlyURLPath =
861 layoutFriendlyURLElement.attributeValue("path");
862
863 LayoutFriendlyURL layoutFriendlyURL =
864 (LayoutFriendlyURL)portletDataContext.getZipEntryAsObject(
865 layoutFriendlyURLPath);
866
867 StagedModelDataHandlerUtil.importStagedModel(
868 portletDataContext, layoutFriendlyURL);
869 }
870
871 deleteMissingLayoutFriendlyURLs(portletDataContext, importedLayout);
872 }
873
874 protected void importLayoutIconImage(
875 PortletDataContext portletDataContext, Layout importedLayout,
876 Element layoutElement)
877 throws Exception {
878
879 String iconImagePath = layoutElement.elementText("icon-image-path");
880
881 byte[] iconBytes = portletDataContext.getZipEntryAsByteArray(
882 iconImagePath);
883
884 if (ArrayUtil.isNotEmpty(iconBytes)) {
885 importedLayout.setIconImage(true);
886
887 if (importedLayout.getIconImageId() == 0) {
888 long iconImageId = CounterLocalServiceUtil.increment();
889
890 importedLayout.setIconImageId(iconImageId);
891 }
892
893 ImageLocalServiceUtil.updateImage(
894 importedLayout.getIconImageId(), iconBytes);
895 }
896 }
897
898 protected void importLinkedLayout(
899 PortletDataContext portletDataContext, Layout layout,
900 Layout importedLayout, Element layoutElement,
901 Map<Long, Layout> newLayoutsMap)
902 throws Exception {
903
904 UnicodeProperties typeSettingsProperties =
905 layout.getTypeSettingsProperties();
906
907 long linkToLayoutId = GetterUtil.getLong(
908 typeSettingsProperties.getProperty(
909 "linkToLayoutId", StringPool.BLANK));
910
911 String linkedToLayoutUuid = layoutElement.attributeValue(
912 "linked-to-layout-uuid");
913
914 if (Validator.isNull(linkedToLayoutUuid)) {
915 return;
916 }
917
918 if (linkToLayoutId <= 0) {
919 updateTypeSettings(portletDataContext, importedLayout, layout);
920
921 return;
922 }
923
924 Element linkedToLayoutElement =
925 portletDataContext.getReferenceDataElement(
926 layout, Layout.class, layout.getGroupId(), linkedToLayoutUuid);
927
928 if (linkedToLayoutElement != null) {
929 String linkedToLayoutPath = linkedToLayoutElement.attributeValue(
930 "path");
931
932 Layout linkedToLayout =
933 (Layout)portletDataContext.getZipEntryAsObject(
934 linkedToLayoutPath);
935
936 StagedModelDataHandlerUtil.importStagedModel(
937 portletDataContext, linkedToLayout);
938
939 Layout importedLinkedLayout = newLayoutsMap.get(linkToLayoutId);
940
941 typeSettingsProperties.setProperty(
942 "privateLayout",
943 String.valueOf(importedLinkedLayout.isPrivateLayout()));
944 typeSettingsProperties.setProperty(
945 "linkToLayoutId",
946 String.valueOf(importedLinkedLayout.getLayoutId()));
947 }
948 else {
949 if (_log.isWarnEnabled()) {
950 StringBundler sb = new StringBundler(6);
951
952 sb.append("Unable to link layout with friendly URL ");
953 sb.append(layout.getFriendlyURL());
954 sb.append(" and layout id ");
955 sb.append(layout.getLayoutId());
956 sb.append(" to layout with layout id ");
957 sb.append(linkToLayoutId);
958
959 _log.warn(sb.toString());
960 }
961 }
962
963 updateTypeSettings(portletDataContext, importedLayout, layout);
964 }
965
966 protected void importTheme(
967 PortletDataContext portletDataContext, Layout layout,
968 Layout importedLayout)
969 throws Exception {
970
971 boolean importThemeSettings = MapUtil.getBoolean(
972 portletDataContext.getParameterMap(),
973 PortletDataHandlerKeys.THEME_REFERENCE);
974
975 if (_log.isDebugEnabled()) {
976 _log.debug("Import theme settings " + importThemeSettings);
977 }
978
979 if (importThemeSettings) {
980 importedLayout.setColorSchemeId(layout.getColorSchemeId());
981 importedLayout.setCss(layout.getCss());
982 importedLayout.setThemeId(layout.getThemeId());
983 importedLayout.setWapColorSchemeId(layout.getWapColorSchemeId());
984 importedLayout.setWapThemeId(layout.getWapThemeId());
985 }
986 else {
987 importedLayout.setColorSchemeId(StringPool.BLANK);
988 importedLayout.setCss(StringPool.BLANK);
989 importedLayout.setThemeId(StringPool.BLANK);
990 importedLayout.setWapColorSchemeId(StringPool.BLANK);
991 importedLayout.setWapThemeId(StringPool.BLANK);
992 }
993 }
994
995 protected void initNewLayoutPermissions(
996 long companyId, long groupId, long userId, Layout layout,
997 Layout importedLayout, boolean privateLayout)
998 throws Exception {
999
1000 boolean addGroupPermissions = true;
1001
1002 Group group = importedLayout.getGroup();
1003
1004 if (privateLayout && group.isUser()) {
1005 addGroupPermissions = false;
1006 }
1007
1008 boolean addGuestPermissions = false;
1009
1010 if (!privateLayout || layout.isTypeControlPanel()) {
1011 addGuestPermissions = true;
1012 }
1013
1014 ResourceLocalServiceUtil.addResources(
1015 companyId, groupId, userId, Layout.class.getName(),
1016 importedLayout.getPlid(), false, addGroupPermissions,
1017 addGuestPermissions);
1018 }
1019
1020 protected void mergePortlets(
1021 Layout layout, String newTypeSettings, String portletsMergeMode) {
1022
1023 try {
1024 UnicodeProperties previousTypeSettingsProperties =
1025 layout.getTypeSettingsProperties();
1026
1027 LayoutTypePortlet previousLayoutType =
1028 (LayoutTypePortlet)layout.getLayoutType();
1029
1030 LayoutTemplate previousLayoutTemplate =
1031 previousLayoutType.getLayoutTemplate();
1032
1033 List<String> previousColumns = previousLayoutTemplate.getColumns();
1034
1035 UnicodeProperties newTypeSettingsProperties = new UnicodeProperties(
1036 true);
1037
1038 newTypeSettingsProperties.load(newTypeSettings);
1039
1040 String layoutTemplateId = newTypeSettingsProperties.getProperty(
1041 LayoutTypePortletConstants.LAYOUT_TEMPLATE_ID);
1042
1043 previousTypeSettingsProperties.setProperty(
1044 LayoutTypePortletConstants.LAYOUT_TEMPLATE_ID,
1045 layoutTemplateId);
1046
1047 String nestedColumnIds = newTypeSettingsProperties.getProperty(
1048 LayoutTypePortletConstants.NESTED_COLUMN_IDS);
1049
1050 if (Validator.isNotNull(nestedColumnIds)) {
1051 previousTypeSettingsProperties.setProperty(
1052 LayoutTypePortletConstants.NESTED_COLUMN_IDS,
1053 nestedColumnIds);
1054
1055 String[] nestedColumnIdsArray = StringUtil.split(
1056 nestedColumnIds);
1057
1058 for (String nestedColumnId : nestedColumnIdsArray) {
1059 String nestedColumnValue =
1060 newTypeSettingsProperties.getProperty(nestedColumnId);
1061
1062 previousTypeSettingsProperties.setProperty(
1063 nestedColumnId, nestedColumnValue);
1064 }
1065 }
1066
1067 LayoutTemplate newLayoutTemplate =
1068 LayoutTemplateLocalServiceUtil.getLayoutTemplate(
1069 layoutTemplateId, false, null);
1070
1071 String[] newPortletIds = new String[0];
1072
1073 for (String columnId : newLayoutTemplate.getColumns()) {
1074 String columnValue = newTypeSettingsProperties.getProperty(
1075 columnId);
1076
1077 String[] portletIds = StringUtil.split(columnValue);
1078
1079 if (!previousColumns.contains(columnId)) {
1080 newPortletIds = ArrayUtil.append(newPortletIds, portletIds);
1081 }
1082 else {
1083 String[] previousPortletIds = StringUtil.split(
1084 previousTypeSettingsProperties.getProperty(columnId));
1085
1086 portletIds = appendPortletIds(
1087 previousPortletIds, portletIds, portletsMergeMode);
1088
1089 previousTypeSettingsProperties.setProperty(
1090 columnId, StringUtil.merge(portletIds));
1091 }
1092 }
1093
1094
1095
1096 String columnId = previousColumns.get(0);
1097
1098 String[] portletIds = StringUtil.split(
1099 previousTypeSettingsProperties.getProperty(columnId));
1100
1101 appendPortletIds(portletIds, newPortletIds, portletsMergeMode);
1102
1103 previousTypeSettingsProperties.setProperty(
1104 columnId, StringUtil.merge(portletIds));
1105
1106 layout.setTypeSettings(previousTypeSettingsProperties.toString());
1107 }
1108 catch (IOException ioe) {
1109 layout.setTypeSettings(newTypeSettings);
1110 }
1111 }
1112
1113 protected void populateElementLayoutMetadata(
1114 Element layoutElement, Layout layout)
1115 throws Exception {
1116
1117 LayoutStagingHandler layoutStagingHandler =
1118 LayoutStagingUtil.getLayoutStagingHandler(layout);
1119
1120 if (layoutStagingHandler != null) {
1121 LayoutRevision layoutRevision =
1122 layoutStagingHandler.getLayoutRevision();
1123
1124 if (layoutRevision != null) {
1125 layoutElement.addAttribute(
1126 "layout-revision-id",
1127 String.valueOf(layoutRevision.getLayoutRevisionId()));
1128 layoutElement.addAttribute(
1129 "layout-branch-id",
1130 String.valueOf(layoutRevision.getLayoutBranchId()));
1131
1132 LayoutBranch layoutBranch = layoutRevision.getLayoutBranch();
1133
1134 layoutElement.addAttribute(
1135 "layout-branch-name",
1136 String.valueOf(layoutBranch.getName()));
1137 }
1138 }
1139
1140 layoutElement.addAttribute("layout-uuid", layout.getUuid());
1141 layoutElement.addAttribute(
1142 "layout-id", String.valueOf(layout.getLayoutId()));
1143 layoutElement.addAttribute(
1144 "layout-priority", String.valueOf(layout.getPriority()));
1145
1146 String layoutPrototypeUuid = layout.getLayoutPrototypeUuid();
1147
1148 if (Validator.isNotNull(layoutPrototypeUuid)) {
1149 LayoutPrototype layoutPrototype =
1150 LayoutPrototypeLocalServiceUtil.
1151 getLayoutPrototypeByUuidAndCompanyId(
1152 layoutPrototypeUuid, layout.getCompanyId());
1153
1154 layoutElement.addAttribute(
1155 "layout-prototype-uuid", layoutPrototypeUuid);
1156 layoutElement.addAttribute(
1157 "layout-prototype-name",
1158 layoutPrototype.getName(LocaleUtil.getDefault()));
1159 }
1160 }
1161
1162 protected void removePortletFromLayoutTypePortlet(
1163 String portletId, LayoutTypePortlet layoutTypePortlet) {
1164
1165 List<String> columnIds = new ArrayList<String>();
1166
1167 LayoutTemplate layoutTemplate = layoutTypePortlet.getLayoutTemplate();
1168
1169 columnIds.addAll(layoutTemplate.getColumns());
1170
1171 String nestedColumnIds = layoutTypePortlet.getTypeSettingsProperty(
1172 LayoutTypePortletConstants.NESTED_COLUMN_IDS);
1173
1174 columnIds.addAll(ListUtil.fromArray(StringUtil.split(nestedColumnIds)));
1175
1176 for (String columnId : columnIds) {
1177 String columnValue = layoutTypePortlet.getTypeSettingsProperty(
1178 columnId);
1179
1180 columnValue = StringUtil.remove(columnValue, portletId);
1181
1182 layoutTypePortlet.setTypeSettingsProperty(columnId, columnValue);
1183 }
1184 }
1185
1186 protected void updateTypeSettings(
1187 PortletDataContext portletDataContext, Layout importedLayout,
1188 Layout layout)
1189 throws PortalException, SystemException {
1190
1191 long groupId = layout.getGroupId();
1192
1193 try {
1194 LayoutTypePortlet importedLayoutType =
1195 (LayoutTypePortlet)importedLayout.getLayoutType();
1196
1197 List<String> importedPortletIds =
1198 importedLayoutType.getPortletIds();
1199
1200 layout.setGroupId(importedLayout.getGroupId());
1201
1202 LayoutTypePortlet layoutTypePortlet =
1203 (LayoutTypePortlet)layout.getLayoutType();
1204
1205
1206
1207 List<String> sourcePortletIds = layoutTypePortlet.getPortletIds();
1208
1209 for (String portletId : sourcePortletIds) {
1210 boolean importPortletConfiguration = false;
1211
1212 try {
1213 Map<String, Boolean> importPortletControlsMap =
1214 LayoutImporter.getImportPortletControlsMap(
1215 portletDataContext.getCompanyId(), portletId,
1216 portletDataContext.getParameterMap(), null,
1217 portletDataContext.getManifestSummary());
1218
1219 importPortletConfiguration = importPortletControlsMap.get(
1220 PortletDataHandlerKeys.PORTLET_CONFIGURATION);
1221 }
1222 catch (Exception e) {
1223 }
1224
1225 if (!importPortletConfiguration &&
1226 !importedPortletIds.contains(portletId)) {
1227
1228 removePortletFromLayoutTypePortlet(
1229 portletId, layoutTypePortlet);
1230 }
1231 }
1232
1233 importedPortletIds.removeAll(layoutTypePortlet.getPortletIds());
1234
1235
1236
1237 if (!importedPortletIds.isEmpty()) {
1238 PortletLocalServiceUtil.deletePortlets(
1239 importedLayout.getCompanyId(),
1240 importedPortletIds.toArray(
1241 new String[importedPortletIds.size()]),
1242 importedLayout.getPlid());
1243 }
1244
1245 importedLayout.setTypeSettingsProperties(
1246 layoutTypePortlet.getTypeSettingsProperties());
1247 }
1248 finally {
1249 layout.setGroupId(groupId);
1250 }
1251 }
1252
1253 private static Log _log = LogFactoryUtil.getLog(
1254 LayoutStagedModelDataHandler.class);
1255
1256 private LayoutLocalServiceHelper _layoutLocalServiceHelper =
1257 (LayoutLocalServiceHelper)PortalBeanLocatorUtil.locate(
1258 LayoutLocalServiceHelper.class.getName());
1259
1260 }