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