001
014
015 package com.liferay.portal.lar;
016
017 import com.liferay.portal.LARFileException;
018 import com.liferay.portal.LARTypeException;
019 import com.liferay.portal.LayoutImportException;
020 import com.liferay.portal.LayoutPrototypeException;
021 import com.liferay.portal.LocaleException;
022 import com.liferay.portal.MissingReferenceException;
023 import com.liferay.portal.NoSuchLayoutException;
024 import com.liferay.portal.NoSuchLayoutPrototypeException;
025 import com.liferay.portal.NoSuchLayoutSetPrototypeException;
026 import com.liferay.portal.kernel.backgroundtask.BackgroundTaskThreadLocal;
027 import com.liferay.portal.kernel.exception.PortalException;
028 import com.liferay.portal.kernel.language.LanguageUtil;
029 import com.liferay.portal.kernel.lar.ExportImportHelperUtil;
030 import com.liferay.portal.kernel.lar.ExportImportThreadLocal;
031 import com.liferay.portal.kernel.lar.ManifestSummary;
032 import com.liferay.portal.kernel.lar.MissingReference;
033 import com.liferay.portal.kernel.lar.MissingReferences;
034 import com.liferay.portal.kernel.lar.PortletDataContext;
035 import com.liferay.portal.kernel.lar.PortletDataContextFactoryUtil;
036 import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
037 import com.liferay.portal.kernel.lar.PortletDataHandlerStatusMessageSenderUtil;
038 import com.liferay.portal.kernel.lar.StagedModelDataHandlerUtil;
039 import com.liferay.portal.kernel.lar.UserIdStrategy;
040 import com.liferay.portal.kernel.log.Log;
041 import com.liferay.portal.kernel.log.LogFactoryUtil;
042 import com.liferay.portal.kernel.search.Indexer;
043 import com.liferay.portal.kernel.search.IndexerRegistryUtil;
044 import com.liferay.portal.kernel.util.ArrayUtil;
045 import com.liferay.portal.kernel.util.Constants;
046 import com.liferay.portal.kernel.util.FileUtil;
047 import com.liferay.portal.kernel.util.GetterUtil;
048 import com.liferay.portal.kernel.util.LocaleUtil;
049 import com.liferay.portal.kernel.util.MapUtil;
050 import com.liferay.portal.kernel.util.ReleaseInfo;
051 import com.liferay.portal.kernel.util.StringPool;
052 import com.liferay.portal.kernel.util.StringUtil;
053 import com.liferay.portal.kernel.util.Tuple;
054 import com.liferay.portal.kernel.util.UnicodeProperties;
055 import com.liferay.portal.kernel.util.Validator;
056 import com.liferay.portal.kernel.xml.Document;
057 import com.liferay.portal.kernel.xml.Element;
058 import com.liferay.portal.kernel.xml.SAXReaderUtil;
059 import com.liferay.portal.kernel.zip.ZipReader;
060 import com.liferay.portal.kernel.zip.ZipReaderFactoryUtil;
061 import com.liferay.portal.model.Group;
062 import com.liferay.portal.model.GroupConstants;
063 import com.liferay.portal.model.Layout;
064 import com.liferay.portal.model.LayoutConstants;
065 import com.liferay.portal.model.LayoutPrototype;
066 import com.liferay.portal.model.LayoutSet;
067 import com.liferay.portal.model.LayoutSetPrototype;
068 import com.liferay.portal.model.Portlet;
069 import com.liferay.portal.model.User;
070 import com.liferay.portal.security.permission.PermissionCacheUtil;
071 import com.liferay.portal.service.GroupLocalServiceUtil;
072 import com.liferay.portal.service.LayoutLocalServiceUtil;
073 import com.liferay.portal.service.LayoutPrototypeLocalServiceUtil;
074 import com.liferay.portal.service.LayoutSetLocalServiceUtil;
075 import com.liferay.portal.service.LayoutSetPrototypeLocalServiceUtil;
076 import com.liferay.portal.service.PortletLocalServiceUtil;
077 import com.liferay.portal.service.ServiceContext;
078 import com.liferay.portal.service.ServiceContextThreadLocal;
079 import com.liferay.portal.service.persistence.LayoutUtil;
080 import com.liferay.portal.service.persistence.UserUtil;
081 import com.liferay.portal.servlet.filters.cache.CacheUtil;
082 import com.liferay.portlet.journal.model.JournalArticle;
083 import com.liferay.portlet.journalcontent.util.JournalContentUtil;
084 import com.liferay.portlet.sites.util.Sites;
085
086 import java.io.File;
087
088 import java.util.ArrayList;
089 import java.util.List;
090 import java.util.Locale;
091 import java.util.Map;
092
093 import org.apache.commons.lang.time.StopWatch;
094
095
108 public class LayoutImporter {
109
110 public void importLayouts(
111 long userId, long groupId, boolean privateLayout,
112 Map<String, String[]> parameterMap, File file)
113 throws Exception {
114
115 try {
116 ExportImportThreadLocal.setLayoutImportInProcess(true);
117
118 doImportLayouts(userId, groupId, privateLayout, parameterMap, file);
119 }
120 finally {
121 ExportImportThreadLocal.setLayoutImportInProcess(false);
122
123 CacheUtil.clearCache();
124 JournalContentUtil.clearCache();
125 PermissionCacheUtil.clearCache();
126 }
127 }
128
129 public MissingReferences validateFile(
130 long userId, long groupId, boolean privateLayout,
131 Map<String, String[]> parameterMap, File file)
132 throws Exception {
133
134 try {
135 ExportImportThreadLocal.setLayoutValidationInProcess(true);
136
137 LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
138 groupId, privateLayout);
139
140 ZipReader zipReader = ZipReaderFactoryUtil.getZipReader(file);
141
142 PortletDataContext portletDataContext =
143 PortletDataContextFactoryUtil.createImportPortletDataContext(
144 layoutSet.getCompanyId(), groupId, parameterMap, null,
145 zipReader);
146
147 validateFile(portletDataContext);
148
149 MissingReferences missingReferences =
150 ExportImportHelperUtil.validateMissingReferences(
151 userId, groupId, parameterMap, file);
152
153 Map<String, MissingReference> dependencyMissingReferences =
154 missingReferences.getDependencyMissingReferences();
155
156 if (!dependencyMissingReferences.isEmpty()) {
157 throw new MissingReferenceException(missingReferences);
158 }
159
160 return missingReferences;
161 }
162 finally {
163 ExportImportThreadLocal.setLayoutValidationInProcess(false);
164 }
165 }
166
167 protected void deleteMissingLayouts(
168 List<String> sourceLayoutUuids, List<Layout> previousLayouts,
169 ServiceContext serviceContext)
170 throws Exception {
171
172 if (_log.isDebugEnabled() && !sourceLayoutUuids.isEmpty()) {
173 _log.debug("Delete missing layouts");
174 }
175
176 for (Layout layout : previousLayouts) {
177 if (!sourceLayoutUuids.contains(layout.getUuid())) {
178 try {
179 LayoutLocalServiceUtil.deleteLayout(
180 layout, false, serviceContext);
181 }
182 catch (NoSuchLayoutException nsle) {
183 }
184 }
185 }
186 }
187
188 protected void doImportLayouts(
189 long userId, long groupId, boolean privateLayout,
190 Map<String, String[]> parameterMap, File file)
191 throws Exception {
192
193 boolean deleteMissingLayouts = MapUtil.getBoolean(
194 parameterMap, PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
195 Boolean.TRUE.booleanValue());
196 boolean deletePortletData = MapUtil.getBoolean(
197 parameterMap, PortletDataHandlerKeys.DELETE_PORTLET_DATA);
198 boolean importCategories = MapUtil.getBoolean(
199 parameterMap, PortletDataHandlerKeys.CATEGORIES);
200 boolean importPermissions = MapUtil.getBoolean(
201 parameterMap, PortletDataHandlerKeys.PERMISSIONS);
202 boolean importLogo = MapUtil.getBoolean(
203 parameterMap, PortletDataHandlerKeys.LOGO);
204 boolean importLayoutSetSettings = MapUtil.getBoolean(
205 parameterMap, PortletDataHandlerKeys.LAYOUT_SET_SETTINGS);
206
207 boolean layoutSetPrototypeLinkEnabled = MapUtil.getBoolean(
208 parameterMap,
209 PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_LINK_ENABLED, true);
210
211 Group group = GroupLocalServiceUtil.getGroup(groupId);
212
213 if (group.isLayoutSetPrototype()) {
214 layoutSetPrototypeLinkEnabled = false;
215 }
216
217 String layoutsImportMode = MapUtil.getString(
218 parameterMap, PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE,
219 PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_MERGE_BY_LAYOUT_UUID);
220 String userIdStrategy = MapUtil.getString(
221 parameterMap, PortletDataHandlerKeys.USER_ID_STRATEGY);
222
223 if (_log.isDebugEnabled()) {
224 _log.debug("Delete portlet data " + deletePortletData);
225 _log.debug("Import categories " + importCategories);
226 _log.debug("Import permissions " + importPermissions);
227 }
228
229 StopWatch stopWatch = null;
230
231 if (_log.isInfoEnabled()) {
232 stopWatch = new StopWatch();
233
234 stopWatch.start();
235 }
236
237 LayoutCache layoutCache = new LayoutCache();
238
239 LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
240 groupId, privateLayout);
241
242 long companyId = layoutSet.getCompanyId();
243
244 User user = UserUtil.findByPrimaryKey(userId);
245
246 ServiceContext serviceContext =
247 ServiceContextThreadLocal.getServiceContext();
248
249 if (serviceContext == null) {
250 serviceContext = new ServiceContext();
251
252 serviceContext.setCompanyId(companyId);
253 serviceContext.setSignedIn(false);
254 serviceContext.setUserId(userId);
255
256 ServiceContextThreadLocal.pushServiceContext(serviceContext);
257 }
258
259 UserIdStrategy strategy = _portletImporter.getUserIdStrategy(
260 user, userIdStrategy);
261
262 if (BackgroundTaskThreadLocal.hasBackgroundTask()) {
263 ManifestSummary manifestSummary =
264 ExportImportHelperUtil.getManifestSummary(
265 userId, groupId, parameterMap, file);
266
267 PortletDataHandlerStatusMessageSenderUtil.sendStatusMessage(
268 "layout", manifestSummary);
269 }
270
271 ZipReader zipReader = ZipReaderFactoryUtil.getZipReader(file);
272
273 PortletDataContext portletDataContext =
274 PortletDataContextFactoryUtil.createImportPortletDataContext(
275 companyId, groupId, parameterMap, strategy, zipReader);
276
277 portletDataContext.setPortetDataContextListener(
278 new PortletDataContextListenerImpl(portletDataContext));
279
280 portletDataContext.setPrivateLayout(privateLayout);
281
282
283
284 validateFile(portletDataContext);
285
286
287
288 long sourceCompanyId = GetterUtil.getLong(
289 _headerElement.attributeValue("company-id"));
290
291 portletDataContext.setSourceCompanyId(sourceCompanyId);
292
293
294
295 long sourceCompanyGroupId = GetterUtil.getLong(
296 _headerElement.attributeValue("company-group-id"));
297
298 portletDataContext.setSourceCompanyGroupId(sourceCompanyGroupId);
299
300
301
302 long sourceGroupId = GetterUtil.getLong(
303 _headerElement.attributeValue("group-id"));
304
305 portletDataContext.setSourceGroupId(sourceGroupId);
306
307
308
309 long sourceUserPersonalSiteGroupId = GetterUtil.getLong(
310 _headerElement.attributeValue("user-personal-site-group-id"));
311
312 portletDataContext.setSourceUserPersonalSiteGroupId(
313 sourceUserPersonalSiteGroupId);
314
315
316
317 String layoutSetPrototypeUuid = _layoutsElement.attributeValue(
318 "layout-set-prototype-uuid");
319
320 String larType = _headerElement.attributeValue("type");
321
322 if (group.isLayoutPrototype() && larType.equals("layout-prototype")) {
323 deleteMissingLayouts = false;
324
325 LayoutPrototype layoutPrototype =
326 LayoutPrototypeLocalServiceUtil.getLayoutPrototype(
327 group.getClassPK());
328
329 String layoutPrototypeUuid = GetterUtil.getString(
330 _headerElement.attributeValue("type-uuid"));
331
332 LayoutPrototype existingLayoutPrototype = null;
333
334 if (Validator.isNotNull(layoutPrototypeUuid)) {
335 try {
336 existingLayoutPrototype =
337 LayoutPrototypeLocalServiceUtil.
338 getLayoutPrototypeByUuidAndCompanyId(
339 layoutPrototypeUuid, companyId);
340 }
341 catch (NoSuchLayoutPrototypeException nslpe) {
342 }
343 }
344
345 if (existingLayoutPrototype == null) {
346 List<Layout> layouts =
347 LayoutLocalServiceUtil.getLayoutsByLayoutPrototypeUuid(
348 layoutPrototype.getUuid());
349
350 layoutPrototype.setUuid(layoutPrototypeUuid);
351
352 LayoutPrototypeLocalServiceUtil.updateLayoutPrototype(
353 layoutPrototype);
354
355 for (Layout layout : layouts) {
356 layout.setLayoutPrototypeUuid(layoutPrototypeUuid);
357
358 LayoutLocalServiceUtil.updateLayout(layout);
359 }
360 }
361 }
362 else if (group.isLayoutSetPrototype() &&
363 larType.equals("layout-set-prototype")) {
364
365 LayoutSetPrototype layoutSetPrototype =
366 LayoutSetPrototypeLocalServiceUtil.getLayoutSetPrototype(
367 group.getClassPK());
368
369 String importedLayoutSetPrototypeUuid = GetterUtil.getString(
370 _headerElement.attributeValue("type-uuid"));
371
372 LayoutSetPrototype existingLayoutSetPrototype = null;
373
374 if (Validator.isNotNull(importedLayoutSetPrototypeUuid)) {
375 try {
376 existingLayoutSetPrototype =
377 LayoutSetPrototypeLocalServiceUtil.
378 getLayoutSetPrototypeByUuidAndCompanyId(
379 importedLayoutSetPrototypeUuid, companyId);
380 }
381 catch (NoSuchLayoutSetPrototypeException nslspe) {
382 }
383 }
384
385 if (existingLayoutSetPrototype == null) {
386 layoutSetPrototype.setUuid(importedLayoutSetPrototypeUuid);
387
388 LayoutSetPrototypeLocalServiceUtil.updateLayoutSetPrototype(
389 layoutSetPrototype);
390 }
391 }
392 else if (larType.equals("layout-set-prototype")) {
393 layoutSetPrototypeUuid = GetterUtil.getString(
394 _headerElement.attributeValue("type-uuid"));
395 }
396
397 if (Validator.isNotNull(layoutSetPrototypeUuid)) {
398 layoutSet.setLayoutSetPrototypeUuid(layoutSetPrototypeUuid);
399 layoutSet.setLayoutSetPrototypeLinkEnabled(
400 layoutSetPrototypeLinkEnabled);
401
402 LayoutSetLocalServiceUtil.updateLayoutSet(layoutSet);
403 }
404
405
406
407 if (importLogo) {
408 String logoPath = _headerElement.attributeValue("logo-path");
409
410 byte[] iconBytes = portletDataContext.getZipEntryAsByteArray(
411 logoPath);
412
413 if (ArrayUtil.isNotEmpty(iconBytes)) {
414 File logo = null;
415
416 try {
417 logo = FileUtil.createTempFile(iconBytes);
418
419 LayoutSetLocalServiceUtil.updateLogo(
420 groupId, privateLayout, true, logo);
421 }
422 finally {
423 FileUtil.delete(logo);
424 }
425 }
426 else {
427 LayoutSetLocalServiceUtil.updateLogo(
428 groupId, privateLayout, false, (File)null);
429 }
430 }
431
432 _themeImporter.importTheme(portletDataContext, layoutSet);
433
434 if (importLayoutSetSettings) {
435 String settings = GetterUtil.getString(
436 _headerElement.elementText("settings"));
437
438 LayoutSetLocalServiceUtil.updateSettings(
439 groupId, privateLayout, settings);
440 }
441
442
443
444
445
446 if (importPermissions) {
447 _permissionImporter.readPortletDataPermissions(portletDataContext);
448 }
449
450 _portletImporter.readAssetCategories(portletDataContext);
451 _portletImporter.readAssetTags(portletDataContext);
452 _portletImporter.readComments(portletDataContext);
453 _portletImporter.readExpandoTables(portletDataContext);
454 _portletImporter.readLocks(portletDataContext);
455 _portletImporter.readRatingsEntries(portletDataContext);
456
457
458
459 List<Layout> previousLayouts = LayoutUtil.findByG_P(
460 groupId, privateLayout);
461
462
463
464 if (Validator.isNotNull(layoutSetPrototypeUuid) &&
465 layoutSetPrototypeLinkEnabled) {
466
467 LayoutSetPrototype layoutSetPrototype =
468 LayoutSetPrototypeLocalServiceUtil.
469 getLayoutSetPrototypeByUuidAndCompanyId(
470 layoutSetPrototypeUuid, companyId);
471
472 for (Layout layout : previousLayouts) {
473 String sourcePrototypeLayoutUuid =
474 layout.getSourcePrototypeLayoutUuid();
475
476 if (Validator.isNull(layout.getSourcePrototypeLayoutUuid())) {
477 continue;
478 }
479
480 Layout sourcePrototypeLayout = LayoutUtil.fetchByUUID_G_P(
481 sourcePrototypeLayoutUuid, layoutSetPrototype.getGroupId(),
482 true);
483
484 if (sourcePrototypeLayout == null) {
485 LayoutLocalServiceUtil.deleteLayout(
486 layout, false, serviceContext);
487 }
488 }
489 }
490
491 List<String> sourceLayoutsUuids = new ArrayList<String>();
492 List<Layout> newLayouts = new ArrayList<Layout>();
493
494 if (_log.isDebugEnabled()) {
495 if (_layoutElements.size() > 0) {
496 _log.debug("Importing layouts");
497 }
498 }
499
500 for (Element layoutElement : _layoutElements) {
501 importLayout(
502 portletDataContext, sourceLayoutsUuids, newLayouts,
503 layoutElement);
504 }
505
506 Element portletsElement = _rootElement.element("portlets");
507
508 List<Element> portletElements = portletsElement.elements("portlet");
509
510
511
512 Map<Long, Layout> newLayoutsMap =
513 (Map<Long, Layout>)portletDataContext.getNewPrimaryKeysMap(
514 Layout.class + ".layout");
515
516 if (deletePortletData) {
517 if (_log.isDebugEnabled()) {
518 if (portletElements.size() > 0) {
519 _log.debug("Deleting portlet data");
520 }
521 }
522
523 for (Element portletElement : portletElements) {
524 String portletId = portletElement.attributeValue("portlet-id");
525 long layoutId = GetterUtil.getLong(
526 portletElement.attributeValue("layout-id"));
527
528 Layout layout = newLayoutsMap.get(layoutId);
529
530 long plid = layout.getPlid();
531
532 portletDataContext.setPlid(plid);
533
534 _portletImporter.deletePortletData(
535 portletDataContext, portletId, plid);
536 }
537 }
538
539
540
541 if (_log.isDebugEnabled()) {
542 if (portletElements.size() > 0) {
543 _log.debug("Importing portlets");
544 }
545 }
546
547 for (Element portletElement : portletElements) {
548 String portletPath = portletElement.attributeValue("path");
549 String portletId = portletElement.attributeValue("portlet-id");
550 long layoutId = GetterUtil.getLong(
551 portletElement.attributeValue("layout-id"));
552 long oldPlid = GetterUtil.getLong(
553 portletElement.attributeValue("old-plid"));
554
555 Portlet portlet = PortletLocalServiceUtil.getPortletById(
556 portletDataContext.getCompanyId(), portletId);
557
558 if (!portlet.isActive() || portlet.isUndeployedPortlet()) {
559 continue;
560 }
561
562 Layout layout = newLayoutsMap.get(layoutId);
563
564 long plid = LayoutConstants.DEFAULT_PLID;
565
566 if (layout != null) {
567 plid = layout.getPlid();
568 }
569
570 portletDataContext.setPlid(plid);
571 portletDataContext.setOldPlid(oldPlid);
572
573 Document portletDocument = SAXReaderUtil.read(
574 portletDataContext.getZipEntryAsString(portletPath));
575
576 portletElement = portletDocument.getRootElement();
577
578
579
580
581
582
583 setPortletScope(portletDataContext, portletElement);
584
585 long portletPreferencesGroupId = groupId;
586
587 Element portletDataElement = portletElement.element("portlet-data");
588
589 boolean[] importPortletControls = getImportPortletControls(
590 companyId, portletId, parameterMap, portletDataElement);
591
592 try {
593 if (layout != null) {
594 portletPreferencesGroupId = layout.getGroupId();
595 }
596
597
598
599 _portletImporter.importPortletPreferences(
600 portletDataContext, layoutSet.getCompanyId(),
601 portletPreferencesGroupId, layout, null, portletElement,
602 importPortletControls[2], importPortletControls[0],
603 importPortletControls[3], false, importPortletControls[1]);
604
605
606
607 if (importPortletControls[1]) {
608 _portletImporter.importPortletData(
609 portletDataContext, portletId, plid,
610 portletDataElement);
611 }
612 }
613 finally {
614 _portletImporter.resetPortletScope(
615 portletDataContext, portletPreferencesGroupId);
616 }
617
618
619
620 if (importPermissions) {
621 _permissionImporter.importPortletPermissions(
622 layoutCache, companyId, groupId, userId, layout,
623 portletElement, portletId);
624 }
625
626
627
628 _portletImporter.importPortletPreferences(
629 portletDataContext, layoutSet.getCompanyId(), groupId, null,
630 null, portletElement, importPortletControls[2],
631 importPortletControls[0], importPortletControls[3], false,
632 importPortletControls[1]);
633 }
634
635 if (importPermissions) {
636 if (userId > 0) {
637 Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
638 User.class);
639
640 indexer.reindex(userId);
641 }
642 }
643
644
645
646 _portletImporter.readAssetLinks(portletDataContext);
647
648
649
650 if (deleteMissingLayouts) {
651 deleteMissingLayouts(
652 sourceLayoutsUuids, previousLayouts, serviceContext);
653 }
654
655
656
657 layoutSet = LayoutSetLocalServiceUtil.updatePageCount(
658 groupId, privateLayout);
659
660
661
662 GroupLocalServiceUtil.updateSite(groupId, true);
663
664
665
666
667 long lastMergeTime = System.currentTimeMillis();
668
669 for (Layout layout : newLayouts) {
670 boolean modifiedTypeSettingsProperties = false;
671
672 UnicodeProperties typeSettingsProperties =
673 layout.getTypeSettingsProperties();
674
675
676
677 String articleId = typeSettingsProperties.getProperty("article-id");
678
679 if (Validator.isNotNull(articleId)) {
680 Map<String, String> articleIds =
681 (Map<String, String>)portletDataContext.
682 getNewPrimaryKeysMap(
683 JournalArticle.class + ".articleId");
684
685 typeSettingsProperties.setProperty(
686 "article-id",
687 MapUtil.getString(articleIds, articleId, articleId));
688
689 modifiedTypeSettingsProperties = true;
690 }
691
692
693
694 if (layoutsImportMode.equals(
695 PortletDataHandlerKeys.
696 LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE)) {
697
698 typeSettingsProperties.setProperty(
699 Sites.LAST_MERGE_TIME, String.valueOf(lastMergeTime));
700
701 modifiedTypeSettingsProperties = true;
702 }
703
704 if (modifiedTypeSettingsProperties) {
705 LayoutUtil.update(layout);
706 }
707 }
708
709
710
711 if (layoutsImportMode.equals(
712 PortletDataHandlerKeys.
713 LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE)) {
714
715 UnicodeProperties settingsProperties =
716 layoutSet.getSettingsProperties();
717
718 String mergeFailFriendlyURLLayouts =
719 settingsProperties.getProperty(
720 Sites.MERGE_FAIL_FRIENDLY_URL_LAYOUTS);
721
722 if (Validator.isNull(mergeFailFriendlyURLLayouts)) {
723 settingsProperties.setProperty(
724 Sites.LAST_MERGE_TIME, String.valueOf(lastMergeTime));
725
726 LayoutSetLocalServiceUtil.updateLayoutSet(layoutSet);
727 }
728 }
729
730
731
732 _deletionSystemEventImporter.importDeletionSystemEvents(
733 portletDataContext);
734
735 if (_log.isInfoEnabled()) {
736 _log.info("Importing layouts takes " + stopWatch.getTime() + " ms");
737 }
738
739 zipReader.close();
740 }
741
742 protected boolean[] getImportPortletControls(
743 long companyId, String portletId,
744 Map<String, String[]> parameterMap, Element portletDataElement)
745 throws Exception {
746
747 boolean importPortletConfiguration = MapUtil.getBoolean(
748 parameterMap, PortletDataHandlerKeys.PORTLET_CONFIGURATION);
749 boolean importPortletConfigurationAll = MapUtil.getBoolean(
750 parameterMap, PortletDataHandlerKeys.PORTLET_CONFIGURATION_ALL);
751 boolean importPortletData = MapUtil.getBoolean(
752 parameterMap, PortletDataHandlerKeys.PORTLET_DATA);
753 boolean importPortletDataAll = MapUtil.getBoolean(
754 parameterMap, PortletDataHandlerKeys.PORTLET_DATA_ALL);
755
756 if (_log.isDebugEnabled()) {
757 _log.debug("Import portlet data " + importPortletData);
758 _log.debug("Import all portlet data " + importPortletDataAll);
759 _log.debug(
760 "Import portlet configuration " + importPortletConfiguration);
761 }
762
763 boolean importCurPortletData = importPortletData;
764
765 String rootPortletId =
766 ExportImportHelperUtil.getExportableRootPortletId(
767 companyId, portletId);
768
769 if (portletDataElement == null) {
770 importCurPortletData = false;
771 }
772 else if (importPortletDataAll) {
773 importCurPortletData = true;
774 }
775 else if (rootPortletId != null) {
776 importCurPortletData =
777 importPortletData &&
778 MapUtil.getBoolean(
779 parameterMap,
780 PortletDataHandlerKeys.PORTLET_DATA +
781 StringPool.UNDERLINE + rootPortletId);
782 }
783
784 boolean importCurPortletArchivedSetups = importPortletConfiguration;
785 boolean importCurPortletSetup = importPortletConfiguration;
786 boolean importCurPortletUserPreferences = importPortletConfiguration;
787
788 if (importPortletConfigurationAll) {
789 importCurPortletArchivedSetups =
790 MapUtil.getBoolean(
791 parameterMap,
792 PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS_ALL);
793 importCurPortletSetup =
794 MapUtil.getBoolean(
795 parameterMap, PortletDataHandlerKeys.PORTLET_SETUP_ALL);
796 importCurPortletUserPreferences =
797 MapUtil.getBoolean(
798 parameterMap,
799 PortletDataHandlerKeys.PORTLET_USER_PREFERENCES_ALL);
800 }
801 else if (rootPortletId != null) {
802 boolean importCurPortletConfiguration =
803 importPortletConfiguration &&
804 MapUtil.getBoolean(
805 parameterMap,
806 PortletDataHandlerKeys.PORTLET_CONFIGURATION +
807 StringPool.UNDERLINE + rootPortletId);
808
809 importCurPortletArchivedSetups =
810 importCurPortletConfiguration &&
811 MapUtil.getBoolean(
812 parameterMap,
813 PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS +
814 StringPool.UNDERLINE + rootPortletId);
815 importCurPortletSetup =
816 importCurPortletConfiguration &&
817 MapUtil.getBoolean(
818 parameterMap,
819 PortletDataHandlerKeys.PORTLET_SETUP +
820 StringPool.UNDERLINE + rootPortletId);
821 importCurPortletUserPreferences =
822 importCurPortletConfiguration &&
823 MapUtil.getBoolean(
824 parameterMap,
825 PortletDataHandlerKeys.PORTLET_USER_PREFERENCES +
826 StringPool.UNDERLINE + rootPortletId);
827 }
828
829 return new boolean[] {
830 importCurPortletArchivedSetups, importCurPortletData,
831 importCurPortletSetup, importCurPortletUserPreferences};
832 }
833
834 protected void importLayout(
835 PortletDataContext portletDataContext,
836 List<String> sourceLayoutsUuids, List<Layout> newLayouts,
837 Element layoutElement)
838 throws Exception {
839
840 String action = layoutElement.attributeValue("action");
841
842 if (!action.equals(Constants.SKIP)) {
843 StagedModelDataHandlerUtil.importStagedModel(
844 portletDataContext, layoutElement);
845
846 List<Layout> portletDataContextNewLayouts =
847 portletDataContext.getNewLayouts();
848
849 newLayouts.addAll(portletDataContextNewLayouts);
850
851 portletDataContextNewLayouts.clear();
852 }
853
854 if (!action.equals(Constants.DELETE)) {
855 sourceLayoutsUuids.add(layoutElement.attributeValue("uuid"));
856 }
857 }
858
859 protected void readXML(PortletDataContext portletDataContext)
860 throws Exception {
861
862 if ((_rootElement != null) && (_headerElement != null) &&
863 (_layoutsElement != null) && (_layoutElements != null)) {
864
865 return;
866 }
867
868 String xml = portletDataContext.getZipEntryAsString("/manifest.xml");
869
870 if (xml == null) {
871 throw new LARFileException("manifest.xml not found in the LAR");
872 }
873
874 try {
875 Document document = SAXReaderUtil.read(xml);
876
877 _rootElement = document.getRootElement();
878
879 portletDataContext.setImportDataRootElement(_rootElement);
880 }
881 catch (Exception e) {
882 throw new LARFileException(e);
883 }
884
885 _headerElement = _rootElement.element("header");
886
887 _layoutsElement = portletDataContext.getImportDataGroupElement(
888 Layout.class);
889
890 _layoutElements = _layoutsElement.elements();
891 }
892
893 protected void setPortletScope(
894 PortletDataContext portletDataContext, Element portletElement) {
895
896
897
898 String scopeLayoutUuid = GetterUtil.getString(
899 portletElement.attributeValue("scope-layout-uuid"));
900 String scopeLayoutType = GetterUtil.getString(
901 portletElement.attributeValue("scope-layout-type"));
902
903 portletDataContext.setScopeLayoutUuid(scopeLayoutUuid);
904 portletDataContext.setScopeType(scopeLayoutType);
905
906
907
908 try {
909 Group scopeGroup = null;
910
911 if (scopeLayoutType.equals("company")) {
912 scopeGroup = GroupLocalServiceUtil.getCompanyGroup(
913 portletDataContext.getCompanyId());
914 }
915 else if (Validator.isNotNull(scopeLayoutUuid)) {
916 boolean privateLayout = GetterUtil.getBoolean(
917 portletElement.attributeValue("private-layout"));
918
919 Layout scopeLayout =
920 LayoutLocalServiceUtil.getLayoutByUuidAndGroupId(
921 scopeLayoutUuid, portletDataContext.getGroupId(),
922 privateLayout);
923
924 if (scopeLayout.hasScopeGroup()) {
925 scopeGroup = scopeLayout.getScopeGroup();
926 }
927 else {
928 String name = String.valueOf(scopeLayout.getPlid());
929
930 scopeGroup = GroupLocalServiceUtil.addGroup(
931 portletDataContext.getUserId(null),
932 GroupConstants.DEFAULT_PARENT_GROUP_ID,
933 Layout.class.getName(), scopeLayout.getPlid(),
934 GroupConstants.DEFAULT_LIVE_GROUP_ID, name, null, 0,
935 true, GroupConstants.DEFAULT_MEMBERSHIP_RESTRICTION,
936 null, false, true, null);
937 }
938
939 Group group = scopeLayout.getGroup();
940
941 if (group.isStaged() && !group.isStagedRemotely()) {
942 try {
943 Layout oldLayout =
944 LayoutLocalServiceUtil.getLayoutByUuidAndGroupId(
945 scopeLayoutUuid,
946 portletDataContext.getSourceGroupId(),
947 privateLayout);
948
949 Group oldScopeGroup = oldLayout.getScopeGroup();
950
951 oldScopeGroup.setLiveGroupId(scopeGroup.getGroupId());
952
953 GroupLocalServiceUtil.updateGroup(oldScopeGroup);
954 }
955 catch (NoSuchLayoutException nsle) {
956 if (_log.isWarnEnabled()) {
957 _log.warn(nsle);
958 }
959 }
960 }
961 }
962
963 if (scopeGroup != null) {
964 portletDataContext.setScopeGroupId(scopeGroup.getGroupId());
965 }
966 }
967 catch (PortalException pe) {
968 }
969 catch (Exception e) {
970 _log.error(e, e);
971 }
972 }
973
974 protected void validateFile(PortletDataContext portletDataContext)
975 throws Exception {
976
977
978
979 readXML(portletDataContext);
980
981 int buildNumber = ReleaseInfo.getBuildNumber();
982
983 int importBuildNumber = GetterUtil.getInteger(
984 _headerElement.attributeValue("build-number"));
985
986 if (buildNumber != importBuildNumber) {
987 throw new LayoutImportException(
988 "LAR build number " + importBuildNumber + " does not match " +
989 "portal build number " + buildNumber);
990 }
991
992
993
994 String larType = _headerElement.attributeValue("type");
995
996 if (!larType.equals("layout-prototype") &&
997 !larType.equals("layout-set") &&
998 !larType.equals("layout-set-prototype")) {
999
1000 throw new LARTypeException(larType);
1001 }
1002
1003
1004
1005 Locale[] sourceAvailableLocales = LocaleUtil.fromLanguageIds(
1006 StringUtil.split(
1007 _headerElement.attributeValue("available-locales")));
1008
1009 Locale[] targetAvailableLocales = LanguageUtil.getAvailableLocales(
1010 portletDataContext.getScopeGroupId());
1011
1012 for (Locale sourceAvailableLocale : sourceAvailableLocales) {
1013 if (!ArrayUtil.contains(
1014 targetAvailableLocales, sourceAvailableLocale)) {
1015
1016 LocaleException le = new LocaleException(
1017 LocaleException.TYPE_EXPORT_IMPORT);
1018
1019 le.setSourceAvailableLocales(sourceAvailableLocales);
1020 le.setTargetAvailableLocales(targetAvailableLocales);
1021
1022 throw le;
1023 }
1024 }
1025
1026
1027
1028 validateLayoutPrototypes(
1029 portletDataContext.getCompanyId(), _layoutsElement,
1030 _layoutElements);
1031 }
1032
1033 protected void validateLayoutPrototypes(
1034 long companyId, Element layoutsElement,
1035 List<Element> layoutElements)
1036 throws Exception {
1037
1038 List<Tuple> missingLayoutPrototypes = new ArrayList<Tuple>();
1039
1040 String layoutSetPrototypeUuid = layoutsElement.attributeValue(
1041 "layout-set-prototype-uuid");
1042
1043 if (Validator.isNotNull(layoutSetPrototypeUuid)) {
1044 try {
1045 LayoutSetPrototypeLocalServiceUtil.
1046 getLayoutSetPrototypeByUuidAndCompanyId(
1047 layoutSetPrototypeUuid, companyId);
1048 }
1049 catch (NoSuchLayoutSetPrototypeException nlspe) {
1050 String layoutSetPrototypeName = layoutsElement.attributeValue(
1051 "layout-set-prototype-name");
1052
1053 missingLayoutPrototypes.add(
1054 new Tuple(
1055 LayoutSetPrototype.class.getName(),
1056 layoutSetPrototypeUuid, layoutSetPrototypeName));
1057 }
1058 }
1059
1060 for (Element layoutElement : layoutElements) {
1061 String action = layoutElement.attributeValue("action");
1062
1063 if (action.equals(Constants.SKIP)) {
1064 continue;
1065 }
1066
1067 String layoutPrototypeUuid = GetterUtil.getString(
1068 layoutElement.attributeValue("layout-prototype-uuid"));
1069
1070 if (Validator.isNotNull(layoutPrototypeUuid)) {
1071 try {
1072 LayoutPrototypeLocalServiceUtil.
1073 getLayoutPrototypeByUuidAndCompanyId(
1074 layoutPrototypeUuid, companyId);
1075 }
1076 catch (NoSuchLayoutPrototypeException nslpe) {
1077 String layoutPrototypeName = GetterUtil.getString(
1078 layoutElement.attributeValue("layout-prototype-name"));
1079
1080 missingLayoutPrototypes.add(
1081 new Tuple(
1082 LayoutPrototype.class.getName(),
1083 layoutPrototypeUuid, layoutPrototypeName));
1084 }
1085 }
1086 }
1087
1088 if (!missingLayoutPrototypes.isEmpty()) {
1089 throw new LayoutPrototypeException(missingLayoutPrototypes);
1090 }
1091 }
1092
1093 private static Log _log = LogFactoryUtil.getLog(LayoutImporter.class);
1094
1095 private DeletionSystemEventImporter _deletionSystemEventImporter =
1096 new DeletionSystemEventImporter();
1097 private Element _headerElement;
1098 private List<Element> _layoutElements;
1099 private Element _layoutsElement;
1100 private PermissionImporter _permissionImporter = new PermissionImporter();
1101 private PortletImporter _portletImporter = new PortletImporter();
1102 private Element _rootElement;
1103 private ThemeImporter _themeImporter = new ThemeImporter();
1104
1105 }