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