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