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