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