1
14
15 package com.liferay.portal.lar;
16
17 import com.liferay.counter.service.CounterLocalServiceUtil;
18 import com.liferay.portal.LARFileException;
19 import com.liferay.portal.LARTypeException;
20 import com.liferay.portal.LayoutImportException;
21 import com.liferay.portal.NoSuchLayoutException;
22 import com.liferay.portal.kernel.cluster.ClusterLinkUtil;
23 import com.liferay.portal.kernel.cluster.Priority;
24 import com.liferay.portal.kernel.exception.PortalException;
25 import com.liferay.portal.kernel.exception.SystemException;
26 import com.liferay.portal.kernel.lar.PortletDataContext;
27 import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
28 import com.liferay.portal.kernel.lar.UserIdStrategy;
29 import com.liferay.portal.kernel.log.Log;
30 import com.liferay.portal.kernel.log.LogFactoryUtil;
31 import com.liferay.portal.kernel.messaging.Message;
32 import com.liferay.portal.kernel.util.ArrayUtil;
33 import com.liferay.portal.kernel.util.FileUtil;
34 import com.liferay.portal.kernel.util.GetterUtil;
35 import com.liferay.portal.kernel.util.LocaleUtil;
36 import com.liferay.portal.kernel.util.LocalizationUtil;
37 import com.liferay.portal.kernel.util.MapUtil;
38 import com.liferay.portal.kernel.util.MethodWrapper;
39 import com.liferay.portal.kernel.util.ReleaseInfo;
40 import com.liferay.portal.kernel.util.StringPool;
41 import com.liferay.portal.kernel.util.StringUtil;
42 import com.liferay.portal.kernel.util.Time;
43 import com.liferay.portal.kernel.util.UnicodeProperties;
44 import com.liferay.portal.kernel.util.Validator;
45 import com.liferay.portal.kernel.xml.Document;
46 import com.liferay.portal.kernel.xml.DocumentException;
47 import com.liferay.portal.kernel.xml.Element;
48 import com.liferay.portal.kernel.xml.SAXReaderUtil;
49 import com.liferay.portal.kernel.zip.ZipReader;
50 import com.liferay.portal.kernel.zip.ZipReaderFactoryUtil;
51 import com.liferay.portal.model.Layout;
52 import com.liferay.portal.model.LayoutSet;
53 import com.liferay.portal.model.LayoutTemplate;
54 import com.liferay.portal.model.LayoutTypePortlet;
55 import com.liferay.portal.model.LayoutTypePortletConstants;
56 import com.liferay.portal.model.PortletConstants;
57 import com.liferay.portal.model.User;
58 import com.liferay.portal.model.impl.ColorSchemeImpl;
59 import com.liferay.portal.service.ImageLocalServiceUtil;
60 import com.liferay.portal.service.LayoutLocalServiceUtil;
61 import com.liferay.portal.service.LayoutSetLocalServiceUtil;
62 import com.liferay.portal.service.LayoutTemplateLocalServiceUtil;
63 import com.liferay.portal.service.ServiceContext;
64 import com.liferay.portal.service.persistence.LayoutUtil;
65 import com.liferay.portal.service.persistence.UserUtil;
66 import com.liferay.portal.theme.ThemeLoader;
67 import com.liferay.portal.theme.ThemeLoaderFactory;
68 import com.liferay.portal.util.PortalUtil;
69 import com.liferay.portal.util.PortletKeys;
70 import com.liferay.portal.util.PropsValues;
71 import com.liferay.portlet.asset.DuplicateVocabularyException;
72 import com.liferay.portlet.asset.model.AssetVocabulary;
73 import com.liferay.portlet.asset.service.AssetVocabularyLocalServiceUtil;
74 import com.liferay.portlet.asset.service.persistence.AssetVocabularyUtil;
75 import com.liferay.portlet.journal.model.JournalArticle;
76
77 import java.io.File;
78 import java.io.IOException;
79 import java.io.InputStream;
80
81 import java.util.ArrayList;
82 import java.util.Date;
83 import java.util.HashMap;
84 import java.util.HashSet;
85 import java.util.List;
86 import java.util.Locale;
87 import java.util.Map;
88 import java.util.Set;
89
90 import org.apache.commons.lang.time.StopWatch;
91
92
105 public class LayoutImporter {
106
107 public void importLayouts(
108 long userId, long groupId, boolean privateLayout,
109 Map<String, String[]> parameterMap, File file)
110 throws PortalException, SystemException {
111
112 boolean deleteMissingLayouts = MapUtil.getBoolean(
113 parameterMap, PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
114 Boolean.TRUE.booleanValue());
115 boolean deletePortletData = MapUtil.getBoolean(
116 parameterMap, PortletDataHandlerKeys.DELETE_PORTLET_DATA);
117 boolean importCategories = MapUtil.getBoolean(
118 parameterMap, PortletDataHandlerKeys.CATEGORIES);
119 boolean importPermissions = MapUtil.getBoolean(
120 parameterMap, PortletDataHandlerKeys.PERMISSIONS);
121 boolean importUserPermissions = MapUtil.getBoolean(
122 parameterMap, PortletDataHandlerKeys.PERMISSIONS);
123 boolean importPortletData = MapUtil.getBoolean(
124 parameterMap, PortletDataHandlerKeys.PORTLET_DATA);
125 boolean importPortletSetup = MapUtil.getBoolean(
126 parameterMap, PortletDataHandlerKeys.PORTLET_SETUP);
127 boolean importPortletArchivedSetups = MapUtil.getBoolean(
128 parameterMap, PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS);
129 boolean importPortletUserPreferences = MapUtil.getBoolean(
130 parameterMap, PortletDataHandlerKeys.PORTLET_USER_PREFERENCES);
131 boolean importTheme = MapUtil.getBoolean(
132 parameterMap, PortletDataHandlerKeys.THEME);
133 String layoutsImportMode = MapUtil.getString(
134 parameterMap, PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE,
135 PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_MERGE_BY_LAYOUT_ID);
136 String portletsMergeMode = MapUtil.getString(
137 parameterMap, PortletDataHandlerKeys.PORTLETS_MERGE_MODE,
138 PortletDataHandlerKeys.PORTLETS_MERGE_MODE_REPLACE);
139 String userIdStrategy = MapUtil.getString(
140 parameterMap, PortletDataHandlerKeys.USER_ID_STRATEGY);
141
142 if (_log.isDebugEnabled()) {
143 _log.debug("Delete portlet data " + deletePortletData);
144 _log.debug("Import categories " + importCategories);
145 _log.debug("Import permissions " + importPermissions);
146 _log.debug("Import user permissions " + importUserPermissions);
147 _log.debug("Import portlet data " + importPortletData);
148 _log.debug("Import portlet setup " + importPortletSetup);
149 _log.debug(
150 "Import portlet archived setups " +
151 importPortletArchivedSetups);
152 _log.debug(
153 "Import portlet user preferences " +
154 importPortletUserPreferences);
155 _log.debug("Import theme " + importTheme);
156 }
157
158 StopWatch stopWatch = null;
159
160 if (_log.isInfoEnabled()) {
161 stopWatch = new StopWatch();
162
163 stopWatch.start();
164 }
165
166 LayoutCache layoutCache = new LayoutCache();
167
168 LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
169 groupId, privateLayout);
170
171 long companyId = layoutSet.getCompanyId();
172
173 User user = UserUtil.findByPrimaryKey(userId);
174
175 UserIdStrategy strategy = _portletImporter.getUserIdStrategy(
176 user, userIdStrategy);
177
178 ZipReader zipReader = ZipReaderFactoryUtil.getZipReader(file);
179
180 PortletDataContext context = new PortletDataContextImpl(
181 companyId, groupId, parameterMap, new HashSet<String>(), strategy,
182 zipReader);
183
184 context.setPortetDataContextListener(
185 new PortletDataContextListenerImpl(context));
186
187 context.setPrivateLayout(privateLayout);
188
189
191 Element root = null;
192 InputStream themeZip = null;
193
194
196 String xml = context.getZipEntryAsString("/manifest.xml");
197
198 if (xml == null) {
199 throw new LARFileException("manifest.xml not found in the LAR");
200 }
201
202 try {
203 Document doc = SAXReaderUtil.read(xml);
204
205 root = doc.getRootElement();
206 }
207 catch (Exception e) {
208 throw new LARFileException(e);
209 }
210
211
213 Element header = root.element("header");
214
215 int buildNumber = ReleaseInfo.getBuildNumber();
216
217 int importBuildNumber = GetterUtil.getInteger(
218 header.attributeValue("build-number"));
219
220 if (buildNumber != importBuildNumber) {
221 throw new LayoutImportException(
222 "LAR build number " + importBuildNumber + " does not match " +
223 "portal build number " + buildNumber);
224 }
225
226
228 String larType = header.attributeValue("type");
229
230 if (!larType.equals("layout-set")) {
231 throw new LARTypeException(
232 "Invalid type of LAR file (" + larType + ")");
233 }
234
235
237 long sourceGroupId = GetterUtil.getLong(
238 header.attributeValue("group-id"));
239
240 context.setSourceGroupId(sourceGroupId);
241
242
244 if (importTheme) {
245 themeZip = context.getZipEntryAsInputStream("theme.zip");
246 }
247
248
250 String themeId = header.attributeValue("theme-id");
251 String colorSchemeId = header.attributeValue("color-scheme-id");
252
253 boolean useThemeZip = false;
254
255 if (themeZip != null) {
256 try {
257 String importThemeId = importTheme(layoutSet, themeZip);
258
259 if (importThemeId != null) {
260 themeId = importThemeId;
261 colorSchemeId =
262 ColorSchemeImpl.getDefaultRegularColorSchemeId();
263
264 useThemeZip = true;
265 }
266
267 if (_log.isDebugEnabled()) {
268 _log.debug(
269 "Importing theme takes " + stopWatch.getTime() + " ms");
270 }
271 }
272 catch (Exception e) {
273 throw new SystemException(e);
274 }
275 }
276
277 boolean wapTheme = false;
278
279 LayoutSetLocalServiceUtil.updateLookAndFeel(
280 groupId, privateLayout, themeId, colorSchemeId, StringPool.BLANK,
281 wapTheme);
282
283
286 if (importPermissions) {
287 _permissionImporter.readPortletDataPermissions(context);
288 }
289
290 if (importCategories) {
291 _portletImporter.readCategories(context);
292 }
293
294 _portletImporter.readComments(context, root);
295 _portletImporter.readLocks(context, root);
296 _portletImporter.readRatings(context, root);
297 _portletImporter.readTags(context, root);
298
299
301 List<Layout> previousLayouts = LayoutUtil.findByG_P(
302 groupId, privateLayout);
303
304 List<Layout> newLayouts = new ArrayList<Layout>();
305
306 Set<Long> newLayoutIds = new HashSet<Long>();
307
308 Map<Long, Long> newLayoutIdPlidMap =
309 (Map<Long, Long>)context.getNewPrimaryKeysMap(Layout.class);
310
311 List<Element> layoutEls = root.element("layouts").elements("layout");
312
313 if (_log.isDebugEnabled()) {
314 if (layoutEls.size() > 0) {
315 _log.debug("Importing layouts");
316 }
317 }
318
319 for (Element layoutRefEl : layoutEls) {
320 long layoutId = GetterUtil.getInteger(
321 layoutRefEl.attributeValue("layout-id"));
322
323 long oldLayoutId = layoutId;
324
325 boolean deleteLayout = GetterUtil.getBoolean(
326 layoutRefEl.attributeValue("delete"));
327
328 if (deleteLayout) {
329 try {
330 LayoutLocalServiceUtil.deleteLayout(
331 context.getGroupId(), privateLayout, oldLayoutId);
332 }
333 catch (NoSuchLayoutException nsle) {
334 _log.warn(
335 "Error deleting layout for {" + sourceGroupId + ", " +
336 privateLayout + ", " + oldLayoutId + "}");
337 }
338
339 continue;
340 }
341
342 String layoutPath = layoutRefEl.attributeValue("path");
343
344 Element layoutEl = null;
345
346 try {
347 Document layoutDoc = SAXReaderUtil.read(
348 context.getZipEntryAsString(layoutPath));
349
350 layoutEl = layoutDoc.getRootElement();
351 }
352 catch (DocumentException de) {
353 throw new SystemException(de);
354 }
355
356 long parentLayoutId = GetterUtil.getInteger(
357 layoutEl.elementText("parent-layout-id"));
358
359 if (_log.isDebugEnabled()) {
360 _log.debug(
361 "Importing layout with layout id " + layoutId +
362 " and parent layout id " + parentLayoutId);
363 }
364
365 long oldPlid = GetterUtil.getInteger(
366 layoutEl.attributeValue("old-plid"));
367
368 String name = layoutEl.elementText("name");
369 String title = layoutEl.elementText("title");
370 String description = layoutEl.elementText("description");
371 String type = layoutEl.elementText("type");
372 String typeSettings = layoutEl.elementText("type-settings");
373 boolean hidden = GetterUtil.getBoolean(
374 layoutEl.elementText("hidden"));
375 String friendlyURL = layoutEl.elementText("friendly-url");
376 boolean iconImage = GetterUtil.getBoolean(
377 layoutEl.elementText("icon-image"));
378
379 byte[] iconBytes = null;
380
381 if (iconImage) {
382 String path = layoutEl.elementText("icon-image-path");
383
384 iconBytes = context.getZipEntryAsByteArray(path);
385 }
386
387 if (useThemeZip) {
388 themeId = StringPool.BLANK;
389 colorSchemeId = StringPool.BLANK;
390 }
391 else {
392 themeId = layoutEl.elementText("theme-id");
393 colorSchemeId = layoutEl.elementText("color-scheme-id");
394 }
395
396 String wapThemeId = layoutEl.elementText("wap-theme-id");
397 String wapColorSchemeId = layoutEl.elementText(
398 "wap-color-scheme-id");
399 String css = layoutEl.elementText("css");
400 int priority = GetterUtil.getInteger(
401 layoutEl.elementText("priority"));
402
403 Layout layout = null;
404
405 if (layoutsImportMode.equals(
406 PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_ADD_AS_NEW)) {
407
408 layoutId = LayoutLocalServiceUtil.getNextLayoutId(
409 groupId, privateLayout);
410 friendlyURL = StringPool.SLASH + layoutId;
411 }
412 else if (layoutsImportMode.equals(
413 PortletDataHandlerKeys.
414 LAYOUTS_IMPORT_MODE_MERGE_BY_LAYOUT_NAME)) {
415
416 Locale locale = LocaleUtil.getDefault();
417
418 String localizedName = LocalizationUtil.getLocalization(
419 name, LocaleUtil.toLanguageId(locale));
420
421 for (Layout curLayout : previousLayouts) {
422 if (curLayout.getName(locale).equals(localizedName)) {
423 layout = curLayout;
424
425 break;
426 }
427 }
428
429 if (layout == null) {
430 layoutId = LayoutLocalServiceUtil.getNextLayoutId(
431 groupId, privateLayout);
432 }
433 }
434 else {
435 layout = LayoutUtil.fetchByG_P_L(
436 groupId, privateLayout, layoutId);
437
438 if (layout == null) {
439 layoutId = LayoutLocalServiceUtil.getNextLayoutId(
440 groupId, privateLayout);
441 }
442 }
443
444 if (_log.isDebugEnabled()) {
445 if (layout == null) {
446 _log.debug(
447 "Layout with {groupId=" + groupId + ",privateLayout=" +
448 privateLayout + ",layoutId=" + layoutId +
449 "} does not exist");
450 }
451 else {
452 _log.debug(
453 "Layout with {groupId=" + groupId + ",privateLayout=" +
454 privateLayout + ",layoutId=" + layoutId +
455 "} exists");
456 }
457 }
458
459 if (layout == null) {
460 long plid = CounterLocalServiceUtil.increment();
461
462 layout = LayoutUtil.create(plid);
463
464 layout.setGroupId(groupId);
465 layout.setPrivateLayout(privateLayout);
466 layout.setLayoutId(layoutId);
467 }
468
469 layout.setCompanyId(user.getCompanyId());
470
471 if (parentLayoutId > 0) {
472 long parentLayoutPlid = newLayoutIdPlidMap.get(parentLayoutId);
473
474 Layout parentLayout = LayoutLocalServiceUtil.getLayout(
475 parentLayoutPlid);
476
477 parentLayoutId = parentLayout.getLayoutId();
478 }
479
480 layout.setParentLayoutId(parentLayoutId);
481 layout.setName(name);
482 layout.setTitle(title);
483 layout.setDescription(description);
484 layout.setType(type);
485
486 if (layout.isTypePortlet() &&
487 Validator.isNotNull(layout.getTypeSettings()) &&
488
489 !portletsMergeMode.equals(
490 PortletDataHandlerKeys.PORTLETS_MERGE_MODE_REPLACE)) {
491
492 mergePortlets(layout, typeSettings, portletsMergeMode);
493 }
494 else if (layout.isTypeLinkToLayout() &&
495 Validator.isNotNull(layout.getTypeSettings())) {
496
497 UnicodeProperties typeSettingsProperties =
498 layout.getTypeSettingsProperties();
499
500 long oldLinkToLayoutId = GetterUtil.getLong(
501 typeSettingsProperties.getProperty("linkToLayoutId"));
502
503 if (oldLinkToLayoutId > 0) {
504 long linkToLayoutPlid = newLayoutIdPlidMap.get(
505 oldLinkToLayoutId);
506
507 Layout linkToLayout = LayoutLocalServiceUtil.getLayout(
508 linkToLayoutPlid);
509
510 typeSettingsProperties.setProperty(
511 "linkToLayoutId",
512 String.valueOf(linkToLayout.getLayoutId()));
513
514 layout.setTypeSettingsProperties(typeSettingsProperties);
515 }
516 else {
517 layout.setTypeSettings(typeSettings);
518 }
519 }
520 else {
521 layout.setTypeSettings(typeSettings);
522 }
523
524 layout.setHidden(hidden);
525 layout.setFriendlyURL(friendlyURL);
526
527 if (iconImage) {
528 layout.setIconImage(iconImage);
529
530 if (layout.isNew()) {
531 long iconImageId = CounterLocalServiceUtil.increment();
532
533 layout.setIconImageId(iconImageId);
534 }
535 }
536
537 layout.setThemeId(themeId);
538 layout.setColorSchemeId(colorSchemeId);
539 layout.setWapThemeId(wapThemeId);
540 layout.setWapColorSchemeId(wapColorSchemeId);
541 layout.setCss(css);
542 layout.setPriority(priority);
543
544 fixTypeSettings(layout);
545
546 LayoutUtil.update(layout, false);
547
548 if ((iconBytes != null) && (iconBytes.length > 0)) {
549 ImageLocalServiceUtil.updateImage(
550 layout.getIconImageId(), iconBytes);
551 }
552
553 context.setPlid(layout.getPlid());
554 context.setOldPlid(oldPlid);
555
556 newLayoutIdPlidMap.put(oldLayoutId, layout.getPlid());
557
558 newLayoutIds.add(layoutId);
559
560 newLayouts.add(layout);
561
562
564 if (importPermissions) {
565 _permissionImporter.importLayoutPermissions(
566 layoutCache, companyId, groupId, userId, layout, layoutEl,
567 root, importUserPermissions);
568 }
569
570 _portletImporter.importPortletData(
571 context, PortletKeys.LAYOUT_CONFIGURATION, null, layoutEl);
572 }
573
574 List<Element> portletEls = root.element("portlets").elements("portlet");
575
576
578 if (deletePortletData) {
579 if (_log.isDebugEnabled()) {
580 if (portletEls.size() > 0) {
581 _log.debug("Deleting portlet data");
582 }
583 }
584
585 for (Element portletRefEl : portletEls) {
586 String portletId = portletRefEl.attributeValue("portlet-id");
587 long layoutId = GetterUtil.getLong(
588 portletRefEl.attributeValue("layout-id"));
589 long plid = newLayoutIdPlidMap.get(layoutId);
590
591 context.setPlid(plid);
592
593 _portletImporter.deletePortletData(context, portletId, plid);
594 }
595 }
596
597
599 if (_log.isDebugEnabled()) {
600 if (portletEls.size() > 0) {
601 _log.debug("Importing portlets");
602 }
603 }
604
605 for (Element portletRefEl : portletEls) {
606 String portletPath = portletRefEl.attributeValue("path");
607 String portletId = portletRefEl.attributeValue("portlet-id");
608 long layoutId = GetterUtil.getLong(
609 portletRefEl.attributeValue("layout-id"));
610 long plid = newLayoutIdPlidMap.get(layoutId);
611 long oldPlid = GetterUtil.getLong(
612 portletRefEl.attributeValue("old-plid"));
613
614 Layout layout = LayoutUtil.findByPrimaryKey(plid);
615
616 context.setPlid(plid);
617 context.setOldPlid(oldPlid);
618
619 Element portletEl = null;
620
621 try {
622 Document portletDoc = SAXReaderUtil.read(
623 context.getZipEntryAsString(portletPath));
624
625 portletEl = portletDoc.getRootElement();
626 }
627 catch (DocumentException de) {
628 throw new SystemException(de);
629 }
630
631
636
638 _portletImporter.importPortletPreferences(
639 context, layoutSet.getCompanyId(), layout.getGroupId(),
640 layout, null, portletEl, importPortletSetup,
641 importPortletArchivedSetups, importPortletUserPreferences,
642 false);
643
644
646 long scopeLayoutId = GetterUtil.getLong(
647 portletEl.attributeValue("scope-layout-id"));
648
649 context.setScopeLayoutId(scopeLayoutId);
650
651
653 Element portletDataEl = portletEl.element("portlet-data");
654
655 if (importPortletData && (portletDataEl != null)) {
656 _portletImporter.importPortletData(
657 context, portletId, plid, portletDataEl);
658 }
659
660
662 if (importPermissions) {
663 _permissionImporter.importPortletPermissions(
664 layoutCache, companyId, groupId, userId, layout, portletEl,
665 portletId, importUserPermissions);
666 }
667
668
670 _portletImporter.importPortletPreferences(
671 context, layoutSet.getCompanyId(), groupId, null, null,
672 portletEl, importPortletSetup, importPortletArchivedSetups,
673 importPortletUserPreferences, false);
674 }
675
676
678 if (deleteMissingLayouts) {
679 deleteMissingLayouts(
680 groupId, privateLayout, newLayoutIds, previousLayouts);
681 }
682
683
685 LayoutSetLocalServiceUtil.updatePageCount(groupId, privateLayout);
686
687 if (_log.isInfoEnabled()) {
688 _log.info("Importing layouts takes " + stopWatch.getTime() + " ms");
689 }
690
691
693 for (Layout layout : newLayouts) {
694 UnicodeProperties typeSettingsProperties =
695 layout.getTypeSettingsProperties();
696
697 String articleId = typeSettingsProperties.getProperty("article-id");
698
699 if (Validator.isNotNull(articleId)) {
700 Map<String, String> articleIds =
701 (Map<String, String>)context.getNewPrimaryKeysMap(
702 JournalArticle.class);
703
704 typeSettingsProperties.setProperty(
705 "article-id",
706 MapUtil.getString(articleIds, articleId, articleId));
707
708 LayoutUtil.update(layout, false);
709 }
710 }
711
712 zipReader.close();
713 }
714
715 protected String[] appendPortletIds(
716 String[] portletIds, String[] newPortletIds, String portletsMergeMode) {
717
718 for (String portletId : newPortletIds) {
719 if (ArrayUtil.contains(portletIds, portletId)) {
720 continue;
721 }
722
723 if (portletsMergeMode.equals(
724 PortletDataHandlerKeys.PORTLETS_MERGE_MODE_ADD_TO_BOTTOM)) {
725
726 portletIds = ArrayUtil.append(portletIds, portletId);
727 }
728 else {
729 portletIds = ArrayUtil.append(
730 new String[] {portletId}, portletIds);
731 }
732 }
733
734 return portletIds;
735 }
736
737 protected void deleteMissingLayouts(
738 long groupId, boolean privateLayout, Set<Long> newLayoutIds,
739 List<Layout> previousLayouts)
740 throws PortalException, SystemException {
741
742
744 if (_log.isDebugEnabled()) {
745 if (newLayoutIds.size() > 0) {
746 _log.debug("Delete missing layouts");
747 }
748 }
749
750 for (Layout layout : previousLayouts) {
751 if (!newLayoutIds.contains(layout.getLayoutId())) {
752 try {
753 LayoutLocalServiceUtil.deleteLayout(layout, false);
754 }
755 catch (NoSuchLayoutException nsle) {
756 }
757 }
758 }
759
760
762 LayoutSetLocalServiceUtil.updatePageCount(groupId, privateLayout);
763 }
764
765 protected void fixTypeSettings(Layout layout)
766 throws PortalException, SystemException {
767
768 if (!layout.isTypeURL()) {
769 return;
770 }
771
772 UnicodeProperties typeSettings = layout.getTypeSettingsProperties();
773
774 String url = GetterUtil.getString(typeSettings.getProperty("url"));
775
776 String friendlyURLPrivateGroupPath =
777 PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_GROUP_SERVLET_MAPPING;
778 String friendlyURLPrivateUserPath =
779 PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING;
780 String friendlyURLPublicPath =
781 PropsValues.LAYOUT_FRIENDLY_URL_PUBLIC_SERVLET_MAPPING;
782
783 if (!url.startsWith(friendlyURLPrivateGroupPath) &&
784 !url.startsWith(friendlyURLPrivateUserPath) &&
785 !url.startsWith(friendlyURLPublicPath)) {
786
787 return;
788 }
789
790 int x = url.indexOf(StringPool.SLASH, 1);
791
792 if (x == -1) {
793 return;
794 }
795
796 int y = url.indexOf(StringPool.SLASH, x + 1);
797
798 if (y == -1) {
799 return;
800 }
801
802 String friendlyURL = url.substring(x, y);
803
804 if (!friendlyURL.equals(LayoutExporter.SAME_GROUP_FRIENDLY_URL)) {
805 return;
806 }
807
808 typeSettings.setProperty(
809 "url",
810 url.substring(0, x) + layout.getGroup().getFriendlyURL() +
811 url.substring(y));
812 }
813
814 protected AssetVocabulary getAssetVocabulary(
815 PortletDataContext context, String vocabularyUuid,
816 String vocabularyName, String userUuid,
817 ServiceContext serviceContext)
818 throws Exception {
819
820 AssetVocabulary assetVocabulary = null;
821
822 try {
823 if (context.getDataStrategy().equals(
824 PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
825
826 AssetVocabulary existingAssetVocabulary =
827 AssetVocabularyUtil.fetchByUUID_G(
828 vocabularyUuid, context.getGroupId());
829
830 if (existingAssetVocabulary == null) {
831 Map<Locale, String> titleMap =
832 new HashMap<Locale, String>();
833
834 titleMap.put(LocaleUtil.getDefault(), vocabularyName);
835
836 assetVocabulary =
837 AssetVocabularyLocalServiceUtil.addVocabulary(
838 vocabularyUuid, context.getUserId(userUuid),
839 titleMap, null, StringPool.BLANK, serviceContext);
840 }
841 else {
842 assetVocabulary =
843 AssetVocabularyLocalServiceUtil.updateVocabulary(
844 existingAssetVocabulary.getVocabularyId(),
845 existingAssetVocabulary.getTitleMap(),
846 existingAssetVocabulary.getDescriptionMap(),
847 existingAssetVocabulary.getSettings(),
848 serviceContext);
849 }
850 }
851 else {
852 Map<Locale, String> titleMap = new HashMap<Locale, String>();
853
854 titleMap.put(LocaleUtil.getDefault(), vocabularyName);
855
856 assetVocabulary = AssetVocabularyLocalServiceUtil.addVocabulary(
857 null, context.getUserId(userUuid), titleMap, null,
858 StringPool.BLANK, serviceContext);
859 }
860 }
861 catch (DuplicateVocabularyException dve) {
862 assetVocabulary =
863 AssetVocabularyLocalServiceUtil.getGroupVocabulary(
864 context.getGroupId(), vocabularyName);
865 }
866
867 return assetVocabulary;
868 }
869
870 protected String importTheme(LayoutSet layoutSet, InputStream themeZip)
871 throws IOException {
872
873 ThemeLoader themeLoader = ThemeLoaderFactory.getDefaultThemeLoader();
874
875 if (themeLoader == null) {
876 _log.error("No theme loaders are deployed");
877
878 return null;
879 }
880
881 ZipReader zipReader = ZipReaderFactoryUtil.getZipReader(themeZip);
882
883 String lookAndFeelXML = zipReader.getEntryAsString(
884 "liferay-look-and-feel.xml");
885
886 String themeId = String.valueOf(layoutSet.getGroupId());
887
888 if (layoutSet.isPrivateLayout()) {
889 themeId += "-private";
890 }
891 else {
892 themeId += "-public";
893 }
894
895 if (PropsValues.THEME_LOADER_NEW_THEME_ID_ON_IMPORT) {
896 Date now = new Date();
897
898 themeId += "-" + Time.getShortTimestamp(now);
899 }
900
901 String themeName = themeId;
902
903 lookAndFeelXML = StringUtil.replace(
904 lookAndFeelXML,
905 new String[] {
906 "[$GROUP_ID$]", "[$THEME_ID$]", "[$THEME_NAME$]"
907 },
908 new String[] {
909 String.valueOf(layoutSet.getGroupId()), themeId, themeName
910 }
911 );
912
913 FileUtil.deltree(
914 themeLoader.getFileStorage() + StringPool.SLASH + themeId);
915
916 List<String> zipEntries = zipReader.getEntries();
917
918 for (String zipEntry : zipEntries) {
919 String key = zipEntry;
920
921 if (key.contains(StringPool.SLASH)) {
922 key = key.substring(key.lastIndexOf(StringPool.SLASH));
923 }
924
925 if (key.equals("liferay-look-and-feel.xml")) {
926 FileUtil.write(
927 themeLoader.getFileStorage() + StringPool.SLASH + themeId +
928 StringPool.SLASH + key,
929 lookAndFeelXML.getBytes());
930 }
931 else {
932 InputStream is = zipReader.getEntryAsInputStream(zipEntry);
933
934 FileUtil.write(
935 themeLoader.getFileStorage() + StringPool.SLASH + themeId +
936 StringPool.SLASH + key,
937 is);
938 }
939 }
940
941 themeLoader.loadThemes();
942
943 MethodWrapper methodWrapper = new MethodWrapper(
944 ThemeLoaderFactory.class.getName(), "loadThemes");
945
946 Message message = new Message();
947 message.setPayload(methodWrapper);
948
949 ClusterLinkUtil.sendMulticastMessage(message, Priority.LEVEL5);
950
951 themeId +=
952 PortletConstants.WAR_SEPARATOR +
953 themeLoader.getServletContextName();
954
955 return PortalUtil.getJsSafePortletId(themeId);
956 }
957
958 protected void mergePortlets(
959 Layout layout, String newTypeSettings, String portletsMergeMode) {
960
961 try {
962 UnicodeProperties previousProps =
963 layout.getTypeSettingsProperties();
964 LayoutTypePortlet previousLayoutType =
965 (LayoutTypePortlet)layout.getLayoutType();
966 List<String> previousColumns =
967 previousLayoutType.getLayoutTemplate().getColumns();
968
969 UnicodeProperties newProps = new UnicodeProperties(true);
970
971 newProps.load(newTypeSettings);
972
973 String layoutTemplateId = newProps.getProperty(
974 LayoutTypePortletConstants.LAYOUT_TEMPLATE_ID);
975
976 LayoutTemplate newLayoutTemplate =
977 LayoutTemplateLocalServiceUtil.getLayoutTemplate(
978 layoutTemplateId, false, null);
979
980 String[] lostPortletIds = new String[0];
981
982 for (String columnId : newLayoutTemplate.getColumns()) {
983 String columnValue =
984 newProps.getProperty(columnId);
985
986 String[] portletIds = StringUtil.split(columnValue);
987
988 if (!previousColumns.contains(columnId)) {
989 lostPortletIds = ArrayUtil.append(
990 lostPortletIds, portletIds);
991 }
992 else {
993
994 String[] previousPortletIds = StringUtil.split(
995 previousProps.getProperty(columnId));
996
997 portletIds = appendPortletIds(
998 previousPortletIds, portletIds, portletsMergeMode);
999
1000 previousProps.setProperty(
1001 columnId, StringUtil.merge(portletIds));
1002 }
1003 }
1004
1005
1007 String columnId = previousColumns.get(0);
1008
1009 String[] portletIds = StringUtil.split(
1010 previousProps.getProperty(columnId));
1011
1012 appendPortletIds(portletIds, lostPortletIds, portletsMergeMode);
1013
1014 previousProps.setProperty(
1015 columnId, StringUtil.merge(portletIds));
1016
1017 layout.setTypeSettings(previousProps.toString());
1018
1019 }
1020 catch (IOException e) {
1021 layout.setTypeSettings(newTypeSettings);
1022 }
1023 }
1024
1025 private static Log _log = LogFactoryUtil.getLog(LayoutImporter.class);
1026
1027 private PermissionImporter _permissionImporter = new PermissionImporter();
1028 private PortletImporter _portletImporter = new PortletImporter();
1029
1030}