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
623 if (!layoutsImportMode.equals(
624 PortletDataHandlerKeys.
625 LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE)) {
626
627 _portletImporter.readExpandoTables(portletDataContext);
628 }
629
630 _portletImporter.readLocks(portletDataContext);
631 _portletImporter.readRatingsEntries(portletDataContext);
632
633
634
635 List<Layout> previousLayouts = LayoutUtil.findByG_P(
636 groupId, privateLayout);
637
638
639
640 if (Validator.isNotNull(layoutSetPrototypeUuid) &&
641 layoutSetPrototypeLinkEnabled) {
642
643 LayoutSetPrototype layoutSetPrototype =
644 LayoutSetPrototypeLocalServiceUtil.
645 getLayoutSetPrototypeByUuidAndCompanyId(
646 layoutSetPrototypeUuid, companyId);
647
648 for (Layout layout : previousLayouts) {
649 String sourcePrototypeLayoutUuid =
650 layout.getSourcePrototypeLayoutUuid();
651
652 if (Validator.isNull(layout.getSourcePrototypeLayoutUuid())) {
653 continue;
654 }
655
656 Layout sourcePrototypeLayout = LayoutUtil.fetchByUUID_G_P(
657 sourcePrototypeLayoutUuid, layoutSetPrototype.getGroupId(),
658 true);
659
660 if (sourcePrototypeLayout == null) {
661 LayoutLocalServiceUtil.deleteLayout(
662 layout, false, serviceContext);
663 }
664 }
665 }
666
667 List<String> sourceLayoutsUuids = new ArrayList<String>();
668 List<Layout> newLayouts = new ArrayList<Layout>();
669
670 if (_log.isDebugEnabled()) {
671 if (_layoutElements.size() > 0) {
672 _log.debug("Importing layouts");
673 }
674 }
675
676 for (Element layoutElement : _layoutElements) {
677 importLayout(
678 portletDataContext, sourceLayoutsUuids, newLayouts,
679 layoutElement);
680 }
681
682
683
684 Map<Long, Layout> newLayoutsMap =
685 (Map<Long, Layout>)portletDataContext.getNewPrimaryKeysMap(
686 Layout.class + ".layout");
687
688 if (deletePortletData) {
689 if (_log.isDebugEnabled()) {
690 if (portletElements.size() > 0) {
691 _log.debug("Deleting portlet data");
692 }
693 }
694
695 for (Element portletElement : portletElements) {
696 String portletId = portletElement.attributeValue("portlet-id");
697 long layoutId = GetterUtil.getLong(
698 portletElement.attributeValue("layout-id"));
699
700 long plid = LayoutConstants.DEFAULT_PLID;
701
702 Layout layout = newLayoutsMap.get(layoutId);
703
704 if (layout != null) {
705 plid = layout.getPlid();
706 }
707
708 portletDataContext.setPlid(plid);
709
710 _portletImporter.deletePortletData(
711 portletDataContext, portletId, plid);
712 }
713 }
714
715
716
717 if (_log.isDebugEnabled()) {
718 if (portletElements.size() > 0) {
719 _log.debug("Importing portlets");
720 }
721 }
722
723 for (Element portletElement : portletElements) {
724 String portletPath = portletElement.attributeValue("path");
725 String portletId = portletElement.attributeValue("portlet-id");
726 long layoutId = GetterUtil.getLong(
727 portletElement.attributeValue("layout-id"));
728 long oldPlid = GetterUtil.getLong(
729 portletElement.attributeValue("old-plid"));
730
731 Portlet portlet = PortletLocalServiceUtil.getPortletById(
732 portletDataContext.getCompanyId(), portletId);
733
734 if (!portlet.isActive() || portlet.isUndeployedPortlet()) {
735 continue;
736 }
737
738 Layout layout = newLayoutsMap.get(layoutId);
739
740 long plid = LayoutConstants.DEFAULT_PLID;
741
742 if (layout != null) {
743 plid = layout.getPlid();
744 }
745
746 portletDataContext.setPlid(plid);
747 portletDataContext.setOldPlid(oldPlid);
748
749 if (BackgroundTaskThreadLocal.hasBackgroundTask()) {
750 PortletDataHandlerStatusMessageSenderUtil.sendStatusMessage(
751 "portlet", portletId, manifestSummary);
752 }
753
754 Document portletDocument = SAXReaderUtil.read(
755 portletDataContext.getZipEntryAsString(portletPath));
756
757 portletElement = portletDocument.getRootElement();
758
759
760
761
762
763
764 setPortletScope(portletDataContext, portletElement);
765
766 long portletPreferencesGroupId = groupId;
767
768 Element portletDataElement = portletElement.element("portlet-data");
769
770 Map<String, Boolean> importPortletControlsMap =
771 getImportPortletControlsMap(
772 companyId, portletId, parameterMap, portletDataElement,
773 manifestSummary);
774
775 try {
776 portletDataContext.setRootPortletId(
777 PortletConstants.getRootPortletId(portletId));
778
779 if (layout != null) {
780 portletPreferencesGroupId = layout.getGroupId();
781 }
782
783
784
785 _portletImporter.importPortletPreferences(
786 portletDataContext, layoutSet.getCompanyId(),
787 portletPreferencesGroupId, layout, null, portletElement,
788 false,
789 importPortletControlsMap.get(
790 PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS),
791 importPortletControlsMap.get(
792 PortletDataHandlerKeys.PORTLET_DATA),
793 importPortletControlsMap.get(
794 PortletDataHandlerKeys.PORTLET_SETUP),
795 importPortletControlsMap.get(
796 PortletDataHandlerKeys.PORTLET_USER_PREFERENCES));
797
798
799
800 if (importPortletControlsMap.get(
801 PortletDataHandlerKeys.PORTLET_DATA)) {
802
803 _portletImporter.importPortletData(
804 portletDataContext, portletId, plid,
805 portletDataElement);
806 }
807 }
808 finally {
809 portletDataContext.setRootPortletId(StringPool.BLANK);
810
811 _portletImporter.resetPortletScope(
812 portletDataContext, portletPreferencesGroupId);
813 }
814
815
816
817 if (importPermissions) {
818 _permissionImporter.importPortletPermissions(
819 layoutCache, companyId, groupId, userId, layout,
820 portletElement, portletId);
821 }
822
823
824
825 _portletImporter.importPortletPreferences(
826 portletDataContext, layoutSet.getCompanyId(), groupId, null,
827 null, portletElement, false,
828 importPortletControlsMap.get(
829 PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS),
830 importPortletControlsMap.get(
831 PortletDataHandlerKeys.PORTLET_DATA),
832 importPortletControlsMap.get(
833 PortletDataHandlerKeys.PORTLET_SETUP),
834 importPortletControlsMap.get(
835 PortletDataHandlerKeys.PORTLET_USER_PREFERENCES));
836 }
837
838
839
840 _portletImporter.readAssetLinks(portletDataContext);
841
842
843
844 if (deleteMissingLayouts) {
845 deleteMissingLayouts(
846 sourceLayoutsUuids, previousLayouts, serviceContext);
847 }
848
849
850
851 layoutSet = LayoutSetLocalServiceUtil.updatePageCount(
852 groupId, privateLayout);
853
854
855
856 GroupLocalServiceUtil.updateSite(groupId, true);
857
858
859
860
861 long lastMergeTime = System.currentTimeMillis();
862
863 for (Layout layout : newLayouts) {
864 boolean modifiedTypeSettingsProperties = false;
865
866 UnicodeProperties typeSettingsProperties =
867 layout.getTypeSettingsProperties();
868
869
870
871 String articleId = typeSettingsProperties.getProperty("article-id");
872
873 if (Validator.isNotNull(articleId)) {
874 Map<String, String> articleIds =
875 (Map<String, String>)portletDataContext.
876 getNewPrimaryKeysMap(
877 JournalArticle.class + ".articleId");
878
879 typeSettingsProperties.setProperty(
880 "article-id",
881 MapUtil.getString(articleIds, articleId, articleId));
882
883 modifiedTypeSettingsProperties = true;
884 }
885
886
887
888 if (layoutsImportMode.equals(
889 PortletDataHandlerKeys.
890 LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE)) {
891
892 typeSettingsProperties.setProperty(
893 Sites.LAST_MERGE_TIME, String.valueOf(lastMergeTime));
894
895 modifiedTypeSettingsProperties = true;
896 }
897
898 if (modifiedTypeSettingsProperties) {
899 LayoutUtil.update(layout);
900 }
901 }
902
903
904
905 if (layoutsImportMode.equals(
906 PortletDataHandlerKeys.
907 LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE)) {
908
909 UnicodeProperties settingsProperties =
910 layoutSet.getSettingsProperties();
911
912 String mergeFailFriendlyURLLayouts =
913 settingsProperties.getProperty(
914 Sites.MERGE_FAIL_FRIENDLY_URL_LAYOUTS);
915
916 if (Validator.isNull(mergeFailFriendlyURLLayouts)) {
917 settingsProperties.setProperty(
918 Sites.LAST_MERGE_TIME, String.valueOf(lastMergeTime));
919
920 LayoutSetLocalServiceUtil.updateLayoutSet(layoutSet);
921 }
922 }
923
924
925
926 updateLayoutPriorities(
927 portletDataContext, _layoutElements, privateLayout);
928
929 if (_log.isInfoEnabled()) {
930 _log.info("Importing layouts takes " + stopWatch.getTime() + " ms");
931 }
932
933 zipReader.close();
934
935 ExportImportHelperUtil.reindex(portletDataContext, userId);
936 }
937
938 protected void importLayout(
939 PortletDataContext portletDataContext,
940 List<String> sourceLayoutsUuids, List<Layout> newLayouts,
941 Element layoutElement)
942 throws Exception {
943
944 String action = layoutElement.attributeValue("action");
945
946 if (!action.equals(Constants.SKIP)) {
947 StagedModelDataHandlerUtil.importStagedModel(
948 portletDataContext, layoutElement);
949
950 List<Layout> portletDataContextNewLayouts =
951 portletDataContext.getNewLayouts();
952
953 newLayouts.addAll(portletDataContextNewLayouts);
954
955 portletDataContextNewLayouts.clear();
956 }
957
958 if (!action.equals(Constants.DELETE)) {
959 sourceLayoutsUuids.add(layoutElement.attributeValue("uuid"));
960 }
961 }
962
963 protected void readXML(PortletDataContext portletDataContext)
964 throws Exception {
965
966 if ((_rootElement != null) && (_headerElement != null) &&
967 (_layoutsElement != null) && (_layoutElements != null)) {
968
969 return;
970 }
971
972 String xml = portletDataContext.getZipEntryAsString("/manifest.xml");
973
974 if (xml == null) {
975 throw new LARFileException("manifest.xml not found in the LAR");
976 }
977
978 try {
979 Document document = SAXReaderUtil.read(xml);
980
981 _rootElement = document.getRootElement();
982
983 portletDataContext.setImportDataRootElement(_rootElement);
984 }
985 catch (Exception e) {
986 throw new LARFileException(e);
987 }
988
989 _headerElement = _rootElement.element("header");
990
991 _layoutsElement = portletDataContext.getImportDataGroupElement(
992 Layout.class);
993
994 _layoutElements = _layoutsElement.elements();
995 }
996
997 protected void setPortletScope(
998 PortletDataContext portletDataContext, Element portletElement) {
999
1000
1001
1002 String scopeLayoutUuid = GetterUtil.getString(
1003 portletElement.attributeValue("scope-layout-uuid"));
1004 String scopeLayoutType = GetterUtil.getString(
1005 portletElement.attributeValue("scope-layout-type"));
1006
1007 portletDataContext.setScopeLayoutUuid(scopeLayoutUuid);
1008 portletDataContext.setScopeType(scopeLayoutType);
1009
1010
1011
1012 try {
1013 Group scopeGroup = null;
1014
1015 if (scopeLayoutType.equals("company")) {
1016 scopeGroup = GroupLocalServiceUtil.getCompanyGroup(
1017 portletDataContext.getCompanyId());
1018 }
1019 else if (Validator.isNotNull(scopeLayoutUuid)) {
1020 Layout scopeLayout =
1021 LayoutLocalServiceUtil.getLayoutByUuidAndGroupId(
1022 scopeLayoutUuid, portletDataContext.getGroupId(),
1023 portletDataContext.isPrivateLayout());
1024
1025 if (scopeLayout.hasScopeGroup()) {
1026 scopeGroup = scopeLayout.getScopeGroup();
1027 }
1028 else {
1029 String name = String.valueOf(scopeLayout.getPlid());
1030
1031 scopeGroup = GroupLocalServiceUtil.addGroup(
1032 portletDataContext.getUserId(null),
1033 GroupConstants.DEFAULT_PARENT_GROUP_ID,
1034 Layout.class.getName(), scopeLayout.getPlid(),
1035 GroupConstants.DEFAULT_LIVE_GROUP_ID, name, null, 0,
1036 true, GroupConstants.DEFAULT_MEMBERSHIP_RESTRICTION,
1037 null, false, true, null);
1038 }
1039
1040 Group group = scopeLayout.getGroup();
1041
1042 if (group.isStaged() && !group.isStagedRemotely()) {
1043 try {
1044 boolean privateLayout = GetterUtil.getBoolean(
1045 portletElement.attributeValue("private-layout"));
1046
1047 Layout oldLayout =
1048 LayoutLocalServiceUtil.getLayoutByUuidAndGroupId(
1049 scopeLayoutUuid,
1050 portletDataContext.getSourceGroupId(),
1051 privateLayout);
1052
1053 Group oldScopeGroup = oldLayout.getScopeGroup();
1054
1055 if (group.isStagingGroup()) {
1056 scopeGroup.setLiveGroupId(
1057 oldScopeGroup.getGroupId());
1058
1059 GroupLocalServiceUtil.updateGroup(scopeGroup);
1060 }
1061 else {
1062 oldScopeGroup.setLiveGroupId(
1063 scopeGroup.getGroupId());
1064
1065 GroupLocalServiceUtil.updateGroup(oldScopeGroup);
1066 }
1067 }
1068 catch (NoSuchLayoutException nsle) {
1069 if (_log.isWarnEnabled()) {
1070 _log.warn(nsle);
1071 }
1072 }
1073 }
1074 }
1075
1076 if (scopeGroup != null) {
1077 portletDataContext.setScopeGroupId(scopeGroup.getGroupId());
1078 }
1079 }
1080 catch (PortalException pe) {
1081 }
1082 catch (Exception e) {
1083 _log.error(e, e);
1084 }
1085 }
1086
1087 protected void updateLayoutPriorities(
1088 PortletDataContext portletDataContext, List<Element> layoutElements,
1089 boolean privateLayout)
1090 throws SystemException {
1091
1092 Map<Long, Layout> layouts =
1093 (Map<Long, Layout>)portletDataContext.getNewPrimaryKeysMap(
1094 Layout.class + ".layout");
1095
1096 Map<Long, Integer> layoutPriorities = new HashMap<Long, Integer>();
1097
1098 int maxPriority = Integer.MIN_VALUE;
1099
1100 for (Element layoutElement : layoutElements) {
1101 String action = layoutElement.attributeValue(Constants.ACTION);
1102
1103 if (action.equals(Constants.SKIP)) {
1104
1105
1106
1107
1108 return;
1109 }
1110
1111 if (action.equals(Constants.ADD)) {
1112 long layoutId = GetterUtil.getLong(
1113 layoutElement.attributeValue("layout-id"));
1114
1115 Layout layout = layouts.get(layoutId);
1116
1117
1118
1119
1120 if (layout == null) {
1121 continue;
1122 }
1123
1124 int layoutPriority = GetterUtil.getInteger(
1125 layoutElement.attributeValue("layout-priority"));
1126
1127 layoutPriorities.put(layout.getPlid(), layoutPriority);
1128
1129 if (maxPriority < layoutPriority) {
1130 maxPriority = layoutPriority;
1131 }
1132 }
1133 }
1134
1135 List<Layout> layoutSetLayouts = LayoutLocalServiceUtil.getLayouts(
1136 portletDataContext.getGroupId(), privateLayout);
1137
1138 for (Layout layout : layoutSetLayouts) {
1139 if (layoutPriorities.containsKey(layout.getPlid())) {
1140 layout.setPriority(layoutPriorities.get(layout.getPlid()));
1141 }
1142 else {
1143 layout.setPriority(++maxPriority);
1144 }
1145
1146 LayoutLocalServiceUtil.updateLayout(layout);
1147 }
1148 }
1149
1150 protected void validateFile(PortletDataContext portletDataContext)
1151 throws Exception {
1152
1153
1154
1155 readXML(portletDataContext);
1156
1157 int buildNumber = ReleaseInfo.getBuildNumber();
1158
1159 int importBuildNumber = GetterUtil.getInteger(
1160 _headerElement.attributeValue("build-number"));
1161
1162 if (buildNumber != importBuildNumber) {
1163 throw new LayoutImportException(
1164 "LAR build number " + importBuildNumber + " does not match " +
1165 "portal build number " + buildNumber);
1166 }
1167
1168
1169
1170 String larType = _headerElement.attributeValue("type");
1171
1172 if (!larType.equals("layout-prototype") &&
1173 !larType.equals("layout-set") &&
1174 !larType.equals("layout-set-prototype")) {
1175
1176 throw new LARTypeException(larType);
1177 }
1178
1179 Group group = GroupLocalServiceUtil.fetchGroup(
1180 portletDataContext.getGroupId());
1181
1182 String layoutsImportMode = MapUtil.getString(
1183 portletDataContext.getParameterMap(),
1184 PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE);
1185
1186 if (larType.equals("layout-prototype") && !group.isLayoutPrototype() &&
1187 !layoutsImportMode.equals(
1188 PortletDataHandlerKeys.
1189 LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE)) {
1190
1191 throw new LARTypeException(
1192 "A page template can only be imported to a page template");
1193 }
1194
1195 if (larType.equals("layout-set") &&
1196 (group.isLayoutPrototype() || group.isLayoutSetPrototype())) {
1197
1198 throw new LARTypeException("A site can only be imported to a site");
1199 }
1200
1201 if (larType.equals("layout-set-prototype") &&
1202 !group.isLayoutSetPrototype() &&
1203 !layoutsImportMode.equals(
1204 PortletDataHandlerKeys.
1205 LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE)) {
1206
1207 throw new LARTypeException(
1208 "A site template can only be imported to a site template");
1209 }
1210
1211
1212
1213 Locale[] sourceAvailableLocales = LocaleUtil.fromLanguageIds(
1214 StringUtil.split(
1215 _headerElement.attributeValue("available-locales")));
1216
1217 Locale[] targetAvailableLocales = LanguageUtil.getAvailableLocales(
1218 portletDataContext.getScopeGroupId());
1219
1220 for (Locale sourceAvailableLocale : sourceAvailableLocales) {
1221 if (!ArrayUtil.contains(
1222 targetAvailableLocales, sourceAvailableLocale)) {
1223
1224 LocaleException le = new LocaleException(
1225 LocaleException.TYPE_EXPORT_IMPORT);
1226
1227 le.setSourceAvailableLocales(sourceAvailableLocales);
1228 le.setTargetAvailableLocales(targetAvailableLocales);
1229
1230 throw le;
1231 }
1232 }
1233
1234
1235
1236 validateLayoutPrototypes(
1237 portletDataContext.getCompanyId(), _layoutsElement,
1238 _layoutElements);
1239 }
1240
1241 protected void validateLayoutPrototypes(
1242 long companyId, Element layoutsElement,
1243 List<Element> layoutElements)
1244 throws Exception {
1245
1246 List<Tuple> missingLayoutPrototypes = new ArrayList<Tuple>();
1247
1248 String layoutSetPrototypeUuid = layoutsElement.attributeValue(
1249 "layout-set-prototype-uuid");
1250
1251 if (Validator.isNotNull(layoutSetPrototypeUuid)) {
1252 try {
1253 LayoutSetPrototypeLocalServiceUtil.
1254 getLayoutSetPrototypeByUuidAndCompanyId(
1255 layoutSetPrototypeUuid, companyId);
1256 }
1257 catch (NoSuchLayoutSetPrototypeException nlspe) {
1258 String layoutSetPrototypeName = layoutsElement.attributeValue(
1259 "layout-set-prototype-name");
1260
1261 missingLayoutPrototypes.add(
1262 new Tuple(
1263 LayoutSetPrototype.class.getName(),
1264 layoutSetPrototypeUuid, layoutSetPrototypeName));
1265 }
1266 }
1267
1268 for (Element layoutElement : layoutElements) {
1269 String action = layoutElement.attributeValue("action");
1270
1271 if (action.equals(Constants.SKIP)) {
1272 continue;
1273 }
1274
1275 String layoutPrototypeUuid = GetterUtil.getString(
1276 layoutElement.attributeValue("layout-prototype-uuid"));
1277
1278 if (Validator.isNotNull(layoutPrototypeUuid)) {
1279 try {
1280 LayoutPrototypeLocalServiceUtil.
1281 getLayoutPrototypeByUuidAndCompanyId(
1282 layoutPrototypeUuid, companyId);
1283 }
1284 catch (NoSuchLayoutPrototypeException nslpe) {
1285 String layoutPrototypeName = GetterUtil.getString(
1286 layoutElement.attributeValue("layout-prototype-name"));
1287
1288 missingLayoutPrototypes.add(
1289 new Tuple(
1290 LayoutPrototype.class.getName(),
1291 layoutPrototypeUuid, layoutPrototypeName));
1292 }
1293 }
1294 }
1295
1296 if (!missingLayoutPrototypes.isEmpty()) {
1297 throw new LayoutPrototypeException(missingLayoutPrototypes);
1298 }
1299 }
1300
1301 private static Log _log = LogFactoryUtil.getLog(LayoutImporter.class);
1302
1303 private DeletionSystemEventImporter _deletionSystemEventImporter =
1304 new DeletionSystemEventImporter();
1305 private Element _headerElement;
1306 private List<Element> _layoutElements;
1307 private Element _layoutsElement;
1308 private PermissionImporter _permissionImporter = new PermissionImporter();
1309 private PortletImporter _portletImporter = new PortletImporter();
1310 private Element _rootElement;
1311 private ThemeImporter _themeImporter = new ThemeImporter();
1312
1313 }