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