001
014
015 package com.liferay.portal.lar;
016
017 import com.liferay.counter.service.CounterLocalServiceUtil;
018 import com.liferay.portal.LARFileException;
019 import com.liferay.portal.LARTypeException;
020 import com.liferay.portal.LayoutImportException;
021 import com.liferay.portal.LayoutPrototypeException;
022 import com.liferay.portal.LocaleException;
023 import com.liferay.portal.NoSuchLayoutException;
024 import com.liferay.portal.NoSuchLayoutPrototypeException;
025 import com.liferay.portal.NoSuchLayoutSetPrototypeException;
026 import com.liferay.portal.kernel.cluster.ClusterExecutorUtil;
027 import com.liferay.portal.kernel.cluster.ClusterRequest;
028 import com.liferay.portal.kernel.exception.PortalException;
029 import com.liferay.portal.kernel.exception.SystemException;
030 import com.liferay.portal.kernel.language.LanguageUtil;
031 import com.liferay.portal.kernel.lar.ExportImportPathUtil;
032 import com.liferay.portal.kernel.lar.ExportImportThreadLocal;
033 import com.liferay.portal.kernel.lar.PortletDataContext;
034 import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
035 import com.liferay.portal.kernel.lar.StagedModelDataHandlerUtil;
036 import com.liferay.portal.kernel.lar.UserIdStrategy;
037 import com.liferay.portal.kernel.log.Log;
038 import com.liferay.portal.kernel.log.LogFactoryUtil;
039 import com.liferay.portal.kernel.search.Indexer;
040 import com.liferay.portal.kernel.search.IndexerRegistryUtil;
041 import com.liferay.portal.kernel.staging.StagingUtil;
042 import com.liferay.portal.kernel.util.ArrayUtil;
043 import com.liferay.portal.kernel.util.CharPool;
044 import com.liferay.portal.kernel.util.ColorSchemeFactoryUtil;
045 import com.liferay.portal.kernel.util.FileUtil;
046 import com.liferay.portal.kernel.util.GetterUtil;
047 import com.liferay.portal.kernel.util.LocaleUtil;
048 import com.liferay.portal.kernel.util.MapUtil;
049 import com.liferay.portal.kernel.util.MethodHandler;
050 import com.liferay.portal.kernel.util.MethodKey;
051 import com.liferay.portal.kernel.util.ReleaseInfo;
052 import com.liferay.portal.kernel.util.StringBundler;
053 import com.liferay.portal.kernel.util.StringPool;
054 import com.liferay.portal.kernel.util.StringUtil;
055 import com.liferay.portal.kernel.util.Time;
056 import com.liferay.portal.kernel.util.Tuple;
057 import com.liferay.portal.kernel.util.UnicodeProperties;
058 import com.liferay.portal.kernel.util.Validator;
059 import com.liferay.portal.kernel.xml.Attribute;
060 import com.liferay.portal.kernel.xml.Document;
061 import com.liferay.portal.kernel.xml.Element;
062 import com.liferay.portal.kernel.xml.Node;
063 import com.liferay.portal.kernel.xml.SAXReaderUtil;
064 import com.liferay.portal.kernel.zip.ZipReader;
065 import com.liferay.portal.kernel.zip.ZipReaderFactoryUtil;
066 import com.liferay.portal.model.Group;
067 import com.liferay.portal.model.Layout;
068 import com.liferay.portal.model.LayoutConstants;
069 import com.liferay.portal.model.LayoutPrototype;
070 import com.liferay.portal.model.LayoutSet;
071 import com.liferay.portal.model.LayoutSetPrototype;
072 import com.liferay.portal.model.LayoutTemplate;
073 import com.liferay.portal.model.LayoutTypePortlet;
074 import com.liferay.portal.model.LayoutTypePortletConstants;
075 import com.liferay.portal.model.Portlet;
076 import com.liferay.portal.model.PortletConstants;
077 import com.liferay.portal.model.ResourceConstants;
078 import com.liferay.portal.model.Role;
079 import com.liferay.portal.model.RoleConstants;
080 import com.liferay.portal.model.User;
081 import com.liferay.portal.security.permission.ActionKeys;
082 import com.liferay.portal.security.permission.PermissionCacheUtil;
083 import com.liferay.portal.service.GroupLocalServiceUtil;
084 import com.liferay.portal.service.ImageLocalServiceUtil;
085 import com.liferay.portal.service.LayoutLocalServiceUtil;
086 import com.liferay.portal.service.LayoutPrototypeLocalServiceUtil;
087 import com.liferay.portal.service.LayoutSetLocalServiceUtil;
088 import com.liferay.portal.service.LayoutSetPrototypeLocalServiceUtil;
089 import com.liferay.portal.service.LayoutTemplateLocalServiceUtil;
090 import com.liferay.portal.service.PortletLocalServiceUtil;
091 import com.liferay.portal.service.ResourceLocalServiceUtil;
092 import com.liferay.portal.service.ResourcePermissionLocalServiceUtil;
093 import com.liferay.portal.service.RoleLocalServiceUtil;
094 import com.liferay.portal.service.ServiceContext;
095 import com.liferay.portal.service.ServiceContextThreadLocal;
096 import com.liferay.portal.service.persistence.LayoutUtil;
097 import com.liferay.portal.service.persistence.UserUtil;
098 import com.liferay.portal.servlet.filters.cache.CacheUtil;
099 import com.liferay.portal.theme.ThemeLoader;
100 import com.liferay.portal.theme.ThemeLoaderFactory;
101 import com.liferay.portal.util.PortalUtil;
102 import com.liferay.portal.util.PortletKeys;
103 import com.liferay.portal.util.PropsValues;
104 import com.liferay.portlet.journal.lar.JournalPortletDataHandler;
105 import com.liferay.portlet.journal.model.JournalArticle;
106 import com.liferay.portlet.journal.service.JournalContentSearchLocalServiceUtil;
107 import com.liferay.portlet.journalcontent.util.JournalContentUtil;
108 import com.liferay.portlet.sites.util.Sites;
109 import com.liferay.portlet.sites.util.SitesUtil;
110
111 import java.io.File;
112 import java.io.IOException;
113 import java.io.InputStream;
114
115 import java.util.ArrayList;
116 import java.util.Date;
117 import java.util.HashSet;
118 import java.util.List;
119 import java.util.Locale;
120 import java.util.Map;
121 import java.util.Set;
122
123 import org.apache.commons.lang.time.StopWatch;
124
125
138 public class LayoutImporter {
139
140 public void importLayouts(
141 long userId, long groupId, boolean privateLayout,
142 Map<String, String[]> parameterMap, File file)
143 throws Exception {
144
145 try {
146 ExportImportThreadLocal.setLayoutImportInProcess(true);
147
148 doImportLayouts(userId, groupId, privateLayout, parameterMap, file);
149 }
150 finally {
151 ExportImportThreadLocal.setLayoutImportInProcess(false);
152
153 CacheUtil.clearCache();
154 JournalContentUtil.clearCache();
155 PermissionCacheUtil.clearCache();
156 }
157 }
158
159 protected String[] appendPortletIds(
160 String[] portletIds, String[] newPortletIds, String portletsMergeMode) {
161
162 for (String portletId : newPortletIds) {
163 if (ArrayUtil.contains(portletIds, portletId)) {
164 continue;
165 }
166
167 if (portletsMergeMode.equals(
168 PortletDataHandlerKeys.PORTLETS_MERGE_MODE_ADD_TO_BOTTOM)) {
169
170 portletIds = ArrayUtil.append(portletIds, portletId);
171 }
172 else {
173 portletIds = ArrayUtil.append(
174 new String[] {portletId}, portletIds);
175 }
176 }
177
178 return portletIds;
179 }
180
181 protected void deleteMissingLayouts(
182 long groupId, boolean privateLayout, List<Layout> newLayouts,
183 List<Layout> previousLayouts, ServiceContext serviceContext)
184 throws Exception {
185
186
187
188 Set<String> existingLayoutUuids = new HashSet<String>();
189
190 Group group = GroupLocalServiceUtil.getGroup(groupId);
191
192 if (group.hasStagingGroup()) {
193 Group stagingGroup = group.getStagingGroup();
194
195 if (stagingGroup.hasPrivateLayouts() ||
196 stagingGroup.hasPublicLayouts()) {
197
198 List<Layout> layouts = LayoutLocalServiceUtil.getLayouts(
199 stagingGroup.getGroupId(), privateLayout);
200
201 for (Layout layout : layouts) {
202 existingLayoutUuids.add(layout.getUuid());
203 }
204 }
205 }
206 else {
207 for (Layout layout : newLayouts) {
208 existingLayoutUuids.add(layout.getUuid());
209 }
210 }
211
212 if (_log.isDebugEnabled() && !existingLayoutUuids.isEmpty()) {
213 _log.debug("Delete missing layouts");
214 }
215
216 for (Layout layout : previousLayouts) {
217 if (!existingLayoutUuids.contains(layout.getUuid())) {
218 try {
219 LayoutLocalServiceUtil.deleteLayout(
220 layout, privateLayout, serviceContext);
221 }
222 catch (NoSuchLayoutException nsle) {
223 }
224 }
225 }
226 }
227
228 protected void doImportLayouts(
229 long userId, long groupId, boolean privateLayout,
230 Map<String, String[]> parameterMap, File file)
231 throws Exception {
232
233 boolean deleteMissingLayouts = MapUtil.getBoolean(
234 parameterMap, PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
235 Boolean.TRUE.booleanValue());
236 boolean deletePortletData = MapUtil.getBoolean(
237 parameterMap, PortletDataHandlerKeys.DELETE_PORTLET_DATA);
238 boolean importCategories = MapUtil.getBoolean(
239 parameterMap, PortletDataHandlerKeys.CATEGORIES);
240 boolean importPermissions = MapUtil.getBoolean(
241 parameterMap, PortletDataHandlerKeys.PERMISSIONS);
242 boolean importPublicLayoutPermissions = MapUtil.getBoolean(
243 parameterMap, PortletDataHandlerKeys.PUBLIC_LAYOUT_PERMISSIONS);
244 boolean importPortletData = MapUtil.getBoolean(
245 parameterMap, PortletDataHandlerKeys.PORTLET_DATA);
246 boolean importPortletSetup = MapUtil.getBoolean(
247 parameterMap, PortletDataHandlerKeys.PORTLET_SETUP);
248 boolean importPortletArchivedSetups = MapUtil.getBoolean(
249 parameterMap, PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS);
250 boolean importPortletUserPreferences = MapUtil.getBoolean(
251 parameterMap, PortletDataHandlerKeys.PORTLET_USER_PREFERENCES);
252 boolean importTheme = MapUtil.getBoolean(
253 parameterMap, PortletDataHandlerKeys.THEME);
254 boolean importThemeSettings = MapUtil.getBoolean(
255 parameterMap, PortletDataHandlerKeys.THEME_REFERENCE);
256 boolean importLogo = MapUtil.getBoolean(
257 parameterMap, PortletDataHandlerKeys.LOGO);
258 boolean importLayoutSetSettings = MapUtil.getBoolean(
259 parameterMap, PortletDataHandlerKeys.LAYOUT_SET_SETTINGS);
260
261 boolean layoutSetPrototypeLinkEnabled = MapUtil.getBoolean(
262 parameterMap,
263 PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_LINK_ENABLED, true);
264
265 Group group = GroupLocalServiceUtil.getGroup(groupId);
266
267 if (group.isLayoutSetPrototype()) {
268 layoutSetPrototypeLinkEnabled = false;
269 }
270
271
272
273 String layoutsImportMode = MapUtil.getString(
274 parameterMap, PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE,
275 PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_MERGE_BY_LAYOUT_UUID);
276 String portletsMergeMode = MapUtil.getString(
277 parameterMap, PortletDataHandlerKeys.PORTLETS_MERGE_MODE,
278 PortletDataHandlerKeys.PORTLETS_MERGE_MODE_REPLACE);
279 String userIdStrategy = MapUtil.getString(
280 parameterMap, PortletDataHandlerKeys.USER_ID_STRATEGY);
281
282 if (_log.isDebugEnabled()) {
283 _log.debug("Delete portlet data " + deletePortletData);
284 _log.debug("Import categories " + importCategories);
285 _log.debug("Import permissions " + importPermissions);
286 _log.debug("Import portlet data " + importPortletData);
287 _log.debug("Import portlet setup " + importPortletSetup);
288 _log.debug(
289 "Import portlet archived setups " +
290 importPortletArchivedSetups);
291 _log.debug(
292 "Import portlet user preferences " +
293 importPortletUserPreferences);
294 _log.debug("Import theme " + importTheme);
295 }
296
297 StopWatch stopWatch = null;
298
299 if (_log.isInfoEnabled()) {
300 stopWatch = new StopWatch();
301
302 stopWatch.start();
303 }
304
305 LayoutCache layoutCache = new LayoutCache();
306
307 LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
308 groupId, privateLayout);
309
310 long companyId = layoutSet.getCompanyId();
311
312 User user = UserUtil.findByPrimaryKey(userId);
313
314 UserIdStrategy strategy = _portletImporter.getUserIdStrategy(
315 user, userIdStrategy);
316
317 ZipReader zipReader = ZipReaderFactoryUtil.getZipReader(file);
318
319 PortletDataContext portletDataContext = new PortletDataContextImpl(
320 companyId, groupId, parameterMap, new HashSet<String>(), strategy,
321 zipReader);
322
323 portletDataContext.setPortetDataContextListener(
324 new PortletDataContextListenerImpl(portletDataContext));
325
326 portletDataContext.setPrivateLayout(privateLayout);
327
328
329
330 Element rootElement = null;
331 InputStream themeZip = null;
332
333
334
335 String xml = portletDataContext.getZipEntryAsString("/manifest.xml");
336
337 if (xml == null) {
338 throw new LARFileException("manifest.xml not found in the LAR");
339 }
340
341 try {
342 Document document = SAXReaderUtil.read(xml);
343
344 rootElement = document.getRootElement();
345 }
346 catch (Exception e) {
347 throw new LARFileException(e);
348 }
349
350
351
352 Element headerElement = rootElement.element("header");
353
354 int buildNumber = ReleaseInfo.getBuildNumber();
355
356 int importBuildNumber = GetterUtil.getInteger(
357 headerElement.attributeValue("build-number"));
358
359 if (buildNumber != importBuildNumber) {
360 throw new LayoutImportException(
361 "LAR build number " + importBuildNumber + " does not match " +
362 "portal build number " + buildNumber);
363 }
364
365
366
367 String larType = headerElement.attributeValue("type");
368
369 if (!larType.equals("layout-prototype") &&
370 !larType.equals("layout-set") &&
371 !larType.equals("layout-set-prototype")) {
372
373 throw new LARTypeException(
374 "Invalid type of LAR file (" + larType + ")");
375 }
376
377
378
379 Locale[] sourceAvailableLocales = LocaleUtil.fromLanguageIds(
380 StringUtil.split(
381 headerElement.attributeValue("available-locales")));
382
383 Locale[] targetAvailableLocales = LanguageUtil.getAvailableLocales();
384
385 for (Locale sourceAvailableLocale : sourceAvailableLocales) {
386 if (!ArrayUtil.contains(
387 targetAvailableLocales, sourceAvailableLocale)) {
388
389 LocaleException le = new LocaleException();
390
391 le.setSourceAvailableLocales(sourceAvailableLocales);
392 le.setTargetAvailableLocales(targetAvailableLocales);
393
394 throw le;
395 }
396 }
397
398
399
400 Element layoutsElement = rootElement.element("layouts");
401
402 List<Element> layoutElements = layoutsElement.elements("layout");
403
404 validateLayoutPrototypes(companyId, layoutsElement, layoutElements);
405
406
407
408 long sourceCompanyGroupId = GetterUtil.getLong(
409 headerElement.attributeValue("company-group-id"));
410
411 portletDataContext.setSourceCompanyGroupId(sourceCompanyGroupId);
412
413
414
415 long sourceGroupId = GetterUtil.getLong(
416 headerElement.attributeValue("group-id"));
417
418 portletDataContext.setSourceGroupId(sourceGroupId);
419
420
421
422 String layoutSetPrototypeUuid = layoutsElement.attributeValue(
423 "layout-set-prototype-uuid");
424
425 if (group.isLayoutPrototype() && larType.equals("layout-prototype")) {
426 deleteMissingLayouts = false;
427
428 LayoutPrototype layoutPrototype =
429 LayoutPrototypeLocalServiceUtil.getLayoutPrototype(
430 group.getClassPK());
431
432 String layoutPrototypeUuid = GetterUtil.getString(
433 headerElement.attributeValue("type-uuid"));
434
435 LayoutPrototype existingLayoutPrototype = null;
436
437 if (Validator.isNotNull(layoutPrototypeUuid)) {
438 try {
439 existingLayoutPrototype =
440 LayoutPrototypeLocalServiceUtil.
441 getLayoutPrototypeByUuidAndCompanyId(
442 layoutPrototypeUuid, companyId);
443 }
444 catch (NoSuchLayoutPrototypeException nslpe) {
445 }
446 }
447
448 if (existingLayoutPrototype == null) {
449 layoutPrototype.setUuid(layoutPrototypeUuid);
450
451 LayoutPrototypeLocalServiceUtil.updateLayoutPrototype(
452 layoutPrototype);
453 }
454 }
455 else if (group.isLayoutSetPrototype() &&
456 larType.equals("layout-set-prototype")) {
457
458 LayoutSetPrototype layoutSetPrototype =
459 LayoutSetPrototypeLocalServiceUtil.getLayoutSetPrototype(
460 group.getClassPK());
461
462 String importedLayoutSetPrototypeUuid = GetterUtil.getString(
463 headerElement.attributeValue("type-uuid"));
464
465 LayoutSetPrototype existingLayoutSetPrototype = null;
466
467 if (Validator.isNotNull(importedLayoutSetPrototypeUuid)) {
468 try {
469 existingLayoutSetPrototype =
470 LayoutSetPrototypeLocalServiceUtil.
471 getLayoutSetPrototypeByUuidAndCompanyId(
472 importedLayoutSetPrototypeUuid, companyId);
473 }
474 catch (NoSuchLayoutSetPrototypeException nslspe) {
475 }
476 }
477
478 if (existingLayoutSetPrototype == null) {
479 layoutSetPrototype.setUuid(importedLayoutSetPrototypeUuid);
480
481 LayoutSetPrototypeLocalServiceUtil.updateLayoutSetPrototype(
482 layoutSetPrototype);
483 }
484 }
485 else if (larType.equals("layout-set-prototype")) {
486 layoutSetPrototypeUuid = GetterUtil.getString(
487 headerElement.attributeValue("type-uuid"));
488 }
489
490 ServiceContext serviceContext =
491 ServiceContextThreadLocal.getServiceContext();
492
493 if (Validator.isNotNull(layoutSetPrototypeUuid)) {
494 layoutSet.setLayoutSetPrototypeUuid(layoutSetPrototypeUuid);
495 layoutSet.setLayoutSetPrototypeLinkEnabled(
496 layoutSetPrototypeLinkEnabled);
497
498 LayoutSetLocalServiceUtil.updateLayoutSet(layoutSet);
499 }
500
501
502
503 if (importTheme) {
504 themeZip = portletDataContext.getZipEntryAsInputStream("theme.zip");
505 }
506
507
508
509 String themeId = layoutSet.getThemeId();
510 String colorSchemeId = layoutSet.getColorSchemeId();
511
512 if (importThemeSettings) {
513 Attribute themeIdAttribute = headerElement.attribute("theme-id");
514
515 if (themeIdAttribute != null) {
516 themeId = themeIdAttribute.getValue();
517 }
518
519 Attribute colorSchemeIdAttribute = headerElement.attribute(
520 "color-scheme-id");
521
522 if (colorSchemeIdAttribute != null) {
523 colorSchemeId = colorSchemeIdAttribute.getValue();
524 }
525 }
526
527 if (importLogo) {
528 String logoPath = headerElement.attributeValue("logo-path");
529
530 byte[] iconBytes = portletDataContext.getZipEntryAsByteArray(
531 logoPath);
532
533 if ((iconBytes != null) && (iconBytes.length > 0)) {
534 File logo = FileUtil.createTempFile(iconBytes);
535
536 LayoutSetLocalServiceUtil.updateLogo(
537 groupId, privateLayout, true, logo);
538 }
539 else {
540 LayoutSetLocalServiceUtil.updateLogo(
541 groupId, privateLayout, false, (File)null);
542 }
543 }
544
545 if (importLayoutSetSettings) {
546 String settings = GetterUtil.getString(
547 headerElement.elementText("settings"));
548
549 LayoutSetLocalServiceUtil.updateSettings(
550 groupId, privateLayout, settings);
551 }
552
553 String css = GetterUtil.getString(headerElement.elementText("css"));
554
555 if (themeZip != null) {
556 String importThemeId = importTheme(layoutSet, themeZip);
557
558 if (importThemeId != null) {
559 themeId = importThemeId;
560 colorSchemeId =
561 ColorSchemeFactoryUtil.getDefaultRegularColorSchemeId();
562 }
563
564 if (_log.isDebugEnabled()) {
565 _log.debug(
566 "Importing theme takes " + stopWatch.getTime() + " ms");
567 }
568 }
569
570 boolean wapTheme = false;
571
572 LayoutSetLocalServiceUtil.updateLookAndFeel(
573 groupId, privateLayout, themeId, colorSchemeId, css, wapTheme);
574
575
576
577
578
579 if (importPermissions) {
580 _permissionImporter.readPortletDataPermissions(portletDataContext);
581 }
582
583 if (importCategories || group.isCompany()) {
584 _portletImporter.readAssetCategories(portletDataContext);
585 }
586
587 _portletImporter.readAssetTags(portletDataContext);
588 _portletImporter.readComments(portletDataContext);
589 _portletImporter.readExpandoTables(portletDataContext);
590 _portletImporter.readLocks(portletDataContext);
591 _portletImporter.readRatingsEntries(portletDataContext);
592
593
594
595 List<Layout> previousLayouts = LayoutUtil.findByG_P(
596 groupId, privateLayout);
597
598
599
600 if (Validator.isNotNull(layoutSetPrototypeUuid) &&
601 layoutSetPrototypeLinkEnabled) {
602
603 LayoutSetPrototype layoutSetPrototype =
604 LayoutSetPrototypeLocalServiceUtil.
605 getLayoutSetPrototypeByUuidAndCompanyId(
606 layoutSetPrototypeUuid, companyId);
607
608 Group layoutSetPrototypeGroup = layoutSetPrototype.getGroup();
609
610 for (Layout layout : previousLayouts) {
611 String sourcePrototypeLayoutUuid =
612 layout.getSourcePrototypeLayoutUuid();
613
614 if (Validator.isNull(layout.getSourcePrototypeLayoutUuid())) {
615 continue;
616 }
617
618 Layout sourcePrototypeLayout = LayoutUtil.fetchByUUID_G_P(
619 sourcePrototypeLayoutUuid,
620 layoutSetPrototypeGroup.getGroupId(), true);
621
622 if (sourcePrototypeLayout == null) {
623 LayoutLocalServiceUtil.deleteLayout(
624 layout, false, serviceContext);
625 }
626 }
627 }
628
629 List<Layout> newLayouts = new ArrayList<Layout>();
630
631 Map<Long, Layout> newLayoutsMap =
632 (Map<Long, Layout>)portletDataContext.getNewPrimaryKeysMap(
633 Layout.class);
634
635 if (_log.isDebugEnabled()) {
636 if (layoutElements.size() > 0) {
637 _log.debug("Importing layouts");
638 }
639 }
640
641 for (Element layoutElement : layoutElements) {
642 importLayout(
643 portletDataContext, user, layoutCache, previousLayouts,
644 newLayouts, newLayoutsMap, portletsMergeMode, themeId,
645 colorSchemeId, layoutsImportMode, privateLayout,
646 importPermissions, importPublicLayoutPermissions,
647 importThemeSettings, rootElement, layoutElement);
648 }
649
650 Element portletsElement = rootElement.element("portlets");
651
652 List<Element> portletElements = portletsElement.elements("portlet");
653
654
655
656 if (deletePortletData) {
657 if (_log.isDebugEnabled()) {
658 if (portletElements.size() > 0) {
659 _log.debug("Deleting portlet data");
660 }
661 }
662
663 for (Element portletElement : portletElements) {
664 String portletId = portletElement.attributeValue("portlet-id");
665 long layoutId = GetterUtil.getLong(
666 portletElement.attributeValue("layout-id"));
667 long plid = newLayoutsMap.get(layoutId).getPlid();
668
669 portletDataContext.setPlid(plid);
670
671 _portletImporter.deletePortletData(
672 portletDataContext, portletId, plid);
673 }
674 }
675
676
677
678 if (_log.isDebugEnabled()) {
679 if (portletElements.size() > 0) {
680 _log.debug("Importing portlets");
681 }
682 }
683
684 for (Element portletElement : portletElements) {
685 String portletPath = portletElement.attributeValue("path");
686 String portletId = portletElement.attributeValue("portlet-id");
687 long layoutId = GetterUtil.getLong(
688 portletElement.attributeValue("layout-id"));
689 long oldPlid = GetterUtil.getLong(
690 portletElement.attributeValue("old-plid"));
691
692 Portlet portlet = PortletLocalServiceUtil.getPortletById(
693 portletDataContext.getCompanyId(), portletId);
694
695 if (!portlet.isActive() || portlet.isUndeployedPortlet()) {
696 continue;
697 }
698
699 Layout layout = newLayoutsMap.get(layoutId);
700
701 long plid = LayoutConstants.DEFAULT_PLID;
702
703 if (layout != null) {
704 plid = layout.getPlid();
705 }
706
707 layout = LayoutUtil.fetchByPrimaryKey(plid);
708
709 if ((layout == null) && !group.isCompany()) {
710 continue;
711 }
712
713 portletDataContext.setPlid(plid);
714 portletDataContext.setOldPlid(oldPlid);
715
716 Document portletDocument = SAXReaderUtil.read(
717 portletDataContext.getZipEntryAsString(portletPath));
718
719 portletElement = portletDocument.getRootElement();
720
721
722
723
724
725
726 _portletImporter.setPortletScope(
727 portletDataContext, portletElement);
728
729 long portletPreferencesGroupId = groupId;
730
731 Element portletDataElement = portletElement.element("portlet-data");
732
733 boolean importData =
734 importPortletData && (portletDataElement != null);
735
736 try {
737 if ((layout != null) && !group.isCompany()) {
738 portletPreferencesGroupId = layout.getGroupId();
739 }
740
741
742
743 _portletImporter.importPortletPreferences(
744 portletDataContext, layoutSet.getCompanyId(),
745 portletPreferencesGroupId, layout, null, portletElement,
746 importPortletSetup, importPortletArchivedSetups,
747 importPortletUserPreferences, false, importData);
748
749
750
751 if (importData) {
752 _portletImporter.importPortletData(
753 portletDataContext, portletId, plid,
754 portletDataElement);
755 }
756 }
757 finally {
758 _portletImporter.resetPortletScope(
759 portletDataContext, portletPreferencesGroupId);
760 }
761
762
763
764 if (importPermissions) {
765 _permissionImporter.importPortletPermissions(
766 layoutCache, companyId, groupId, userId, layout,
767 portletElement, portletId);
768 }
769
770
771
772 _portletImporter.importPortletPreferences(
773 portletDataContext, layoutSet.getCompanyId(), groupId, null,
774 null, portletElement, importPortletSetup,
775 importPortletArchivedSetups, importPortletUserPreferences,
776 false, importData);
777 }
778
779 if (importPermissions) {
780 if (userId > 0) {
781 Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
782 User.class);
783
784 indexer.reindex(userId);
785 }
786 }
787
788
789
790 _portletImporter.readAssetLinks(portletDataContext);
791
792
793
794 if (deleteMissingLayouts) {
795 deleteMissingLayouts(
796 groupId, privateLayout, newLayouts, previousLayouts,
797 serviceContext);
798 }
799
800
801
802 layoutSet = LayoutSetLocalServiceUtil.updatePageCount(
803 groupId, privateLayout);
804
805 if (_log.isInfoEnabled()) {
806 _log.info("Importing layouts takes " + stopWatch.getTime() + " ms");
807 }
808
809
810
811 GroupLocalServiceUtil.updateSite(groupId, true);
812
813
814
815
816 long lastMergeTime = System.currentTimeMillis();
817
818 for (Layout layout : newLayouts) {
819 boolean modifiedTypeSettingsProperties = false;
820
821 UnicodeProperties typeSettingsProperties =
822 layout.getTypeSettingsProperties();
823
824
825
826 String articleId = typeSettingsProperties.getProperty("article-id");
827
828 if (Validator.isNotNull(articleId)) {
829 Map<String, String> articleIds =
830 (Map<String, String>)portletDataContext.
831 getNewPrimaryKeysMap(
832 JournalArticle.class + ".articleId");
833
834 typeSettingsProperties.setProperty(
835 "article-id",
836 MapUtil.getString(articleIds, articleId, articleId));
837
838 modifiedTypeSettingsProperties = true;
839 }
840
841
842
843 if (layoutsImportMode.equals(
844 PortletDataHandlerKeys.
845 LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE)) {
846
847 typeSettingsProperties.setProperty(
848 Sites.LAST_MERGE_TIME, String.valueOf(lastMergeTime));
849
850 modifiedTypeSettingsProperties = true;
851 }
852
853 if (modifiedTypeSettingsProperties) {
854 LayoutUtil.update(layout);
855 }
856 }
857
858
859
860 if (layoutsImportMode.equals(
861 PortletDataHandlerKeys.
862 LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE)) {
863
864 UnicodeProperties settingsProperties =
865 layoutSet.getSettingsProperties();
866
867 settingsProperties.setProperty(
868 Sites.LAST_MERGE_TIME, String.valueOf(lastMergeTime));
869
870 LayoutSetLocalServiceUtil.updateLayoutSet(layoutSet);
871 }
872
873 zipReader.close();
874 }
875
876 protected void fixTypeSettings(Layout layout) throws Exception {
877 if (!layout.isTypeURL()) {
878 return;
879 }
880
881 UnicodeProperties typeSettings = layout.getTypeSettingsProperties();
882
883 String url = GetterUtil.getString(typeSettings.getProperty("url"));
884
885 String friendlyURLPrivateGroupPath =
886 PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_GROUP_SERVLET_MAPPING;
887 String friendlyURLPrivateUserPath =
888 PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING;
889 String friendlyURLPublicPath =
890 PropsValues.LAYOUT_FRIENDLY_URL_PUBLIC_SERVLET_MAPPING;
891
892 if (!url.startsWith(friendlyURLPrivateGroupPath) &&
893 !url.startsWith(friendlyURLPrivateUserPath) &&
894 !url.startsWith(friendlyURLPublicPath)) {
895
896 return;
897 }
898
899 int x = url.indexOf(CharPool.SLASH, 1);
900
901 if (x == -1) {
902 return;
903 }
904
905 int y = url.indexOf(CharPool.SLASH, x + 1);
906
907 if (y == -1) {
908 return;
909 }
910
911 String friendlyURL = url.substring(x, y);
912
913 if (!friendlyURL.equals(LayoutExporter.SAME_GROUP_FRIENDLY_URL)) {
914 return;
915 }
916
917 Group group = layout.getGroup();
918
919 typeSettings.setProperty(
920 "url",
921 url.substring(0, x) + group.getFriendlyURL() + url.substring(y));
922 }
923
924 protected String getLayoutSetPrototypePath(
925 PortletDataContext portletDataContext, String layoutSetPrototypeUuid) {
926
927 return ExportImportPathUtil.getSourceRootPath(portletDataContext) +
928 "/layout-set-prototype/" + layoutSetPrototypeUuid;
929 }
930
931 protected void importJournalArticle(
932 PortletDataContext portletDataContext, Layout layout,
933 Element layoutElement)
934 throws Exception {
935
936 UnicodeProperties typeSettingsProperties =
937 layout.getTypeSettingsProperties();
938
939 String articleId = typeSettingsProperties.getProperty(
940 "article-id", StringPool.BLANK);
941
942 if (Validator.isNull(articleId)) {
943 return;
944 }
945
946 JournalPortletDataHandler.importReferencedData(
947 portletDataContext, layoutElement);
948
949 Element structureElement = layoutElement.element("structure");
950
951 if (structureElement != null) {
952 StagedModelDataHandlerUtil.importStagedModel(
953 portletDataContext, structureElement);
954 }
955
956 Element templateElement = layoutElement.element("template");
957
958 if (templateElement != null) {
959 StagedModelDataHandlerUtil.importStagedModel(
960 portletDataContext, templateElement);
961 }
962
963 Element articleElement = layoutElement.element("article");
964
965 if (articleElement != null) {
966 JournalPortletDataHandler.importArticle(
967 portletDataContext, articleElement);
968 }
969
970 Map<String, String> articleIds =
971 (Map<String, String>)portletDataContext.getNewPrimaryKeysMap(
972 JournalArticle.class + ".articleId");
973
974 articleId = MapUtil.getString(articleIds, articleId, articleId);
975
976 typeSettingsProperties.setProperty("article-id", articleId);
977
978 JournalContentSearchLocalServiceUtil.updateContentSearch(
979 portletDataContext.getScopeGroupId(), layout.isPrivateLayout(),
980 layout.getLayoutId(), StringPool.BLANK, articleId, true);
981 }
982
983 protected void importLayout(
984 PortletDataContext portletDataContext, User user,
985 LayoutCache layoutCache, List<Layout> previousLayouts,
986 List<Layout> newLayouts, Map<Long, Layout> newLayoutsMap,
987 String portletsMergeMode, String themeId, String colorSchemeId,
988 String layoutsImportMode, boolean privateLayout,
989 boolean importPermissions, boolean importPublicLayoutPermissions,
990 boolean importThemeSettings, Element rootElement,
991 Element layoutElement)
992 throws Exception {
993
994 long groupId = portletDataContext.getGroupId();
995
996 String layoutUuid = GetterUtil.getString(
997 layoutElement.attributeValue("layout-uuid"));
998
999 long layoutId = GetterUtil.getInteger(
1000 layoutElement.attributeValue("layout-id"));
1001
1002 long oldLayoutId = layoutId;
1003
1004 boolean deleteLayout = GetterUtil.getBoolean(
1005 layoutElement.attributeValue("delete"));
1006
1007 if (deleteLayout) {
1008 Layout layout = LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
1009 layoutUuid, groupId, privateLayout);
1010
1011 if (layout != null) {
1012 newLayoutsMap.put(oldLayoutId, layout);
1013
1014 ServiceContext serviceContext =
1015 ServiceContextThreadLocal.getServiceContext();
1016
1017 LayoutLocalServiceUtil.deleteLayout(
1018 layout, false, serviceContext);
1019 }
1020
1021 return;
1022 }
1023
1024 String path = layoutElement.attributeValue("path");
1025
1026 if (!portletDataContext.isPathNotProcessed(path)) {
1027 return;
1028 }
1029
1030 Layout layout = (Layout)portletDataContext.getZipEntryAsObject(path);
1031
1032 Layout existingLayout = null;
1033 Layout importedLayout = null;
1034
1035 String friendlyURL = layout.getFriendlyURL();
1036
1037 if (layoutsImportMode.equals(
1038 PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_ADD_AS_NEW)) {
1039
1040 layoutId = LayoutLocalServiceUtil.getNextLayoutId(
1041 groupId, privateLayout);
1042 friendlyURL = StringPool.SLASH + layoutId;
1043 }
1044 else if (layoutsImportMode.equals(
1045 PortletDataHandlerKeys.
1046 LAYOUTS_IMPORT_MODE_MERGE_BY_LAYOUT_NAME)) {
1047
1048 Locale locale = LocaleUtil.getDefault();
1049
1050 String localizedName = layout.getName(locale);
1051
1052 for (Layout curLayout : previousLayouts) {
1053 if (localizedName.equals(curLayout.getName(locale)) ||
1054 friendlyURL.equals(curLayout.getFriendlyURL())) {
1055
1056 existingLayout = curLayout;
1057
1058 break;
1059 }
1060 }
1061
1062 if (existingLayout == null) {
1063 layoutId = LayoutLocalServiceUtil.getNextLayoutId(
1064 groupId, privateLayout);
1065 }
1066 }
1067 else if (layoutsImportMode.equals(
1068 PortletDataHandlerKeys.
1069 LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE)) {
1070
1071 existingLayout = LayoutUtil.fetchByG_P_SPLU(
1072 groupId, privateLayout, layout.getUuid());
1073
1074 if (SitesUtil.isLayoutModifiedSinceLastMerge(existingLayout)) {
1075 newLayoutsMap.put(oldLayoutId, existingLayout);
1076
1077 return;
1078 }
1079 }
1080 else {
1081
1082
1083
1084
1085 existingLayout = LayoutUtil.fetchByUUID_G_P(
1086 layout.getUuid(), groupId, privateLayout);
1087
1088 if (existingLayout == null) {
1089 existingLayout = LayoutUtil.fetchByG_P_F(
1090 groupId, privateLayout, friendlyURL);
1091 }
1092
1093 if (existingLayout == null) {
1094 layoutId = LayoutLocalServiceUtil.getNextLayoutId(
1095 groupId, privateLayout);
1096 }
1097 }
1098
1099 if (_log.isDebugEnabled()) {
1100 if (existingLayout == null) {
1101 _log.debug(
1102 "Layout with {groupId=" + groupId + ",privateLayout=" +
1103 privateLayout + ",layoutId=" + layoutId +
1104 "} does not exist");
1105 }
1106 else {
1107 _log.debug(
1108 "Layout with {groupId=" + groupId + ",privateLayout=" +
1109 privateLayout + ",layoutId=" + layoutId + "} exists");
1110 }
1111 }
1112
1113 if (existingLayout == null) {
1114 long plid = CounterLocalServiceUtil.increment();
1115
1116 importedLayout = LayoutUtil.create(plid);
1117
1118 if (layoutsImportMode.equals(
1119 PortletDataHandlerKeys.
1120 LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE)) {
1121
1122 importedLayout.setSourcePrototypeLayoutUuid(layout.getUuid());
1123
1124 layoutId = LayoutLocalServiceUtil.getNextLayoutId(
1125 groupId, privateLayout);
1126 }
1127 else {
1128 importedLayout.setCreateDate(layout.getCreateDate());
1129 importedLayout.setModifiedDate(layout.getModifiedDate());
1130 importedLayout.setLayoutPrototypeUuid(
1131 layout.getLayoutPrototypeUuid());
1132 importedLayout.setLayoutPrototypeLinkEnabled(
1133 layout.isLayoutPrototypeLinkEnabled());
1134 importedLayout.setSourcePrototypeLayoutUuid(
1135 layout.getSourcePrototypeLayoutUuid());
1136 }
1137
1138 importedLayout.setUuid(layout.getUuid());
1139 importedLayout.setGroupId(groupId);
1140 importedLayout.setPrivateLayout(privateLayout);
1141 importedLayout.setLayoutId(layoutId);
1142
1143
1144
1145 boolean addGroupPermissions = true;
1146
1147 Group group = importedLayout.getGroup();
1148
1149 if (privateLayout && group.isUser()) {
1150 addGroupPermissions = false;
1151 }
1152
1153 boolean addGuestPermissions = false;
1154
1155 if (!privateLayout || layout.isTypeControlPanel()) {
1156 addGuestPermissions = true;
1157 }
1158
1159 ResourceLocalServiceUtil.addResources(
1160 user.getCompanyId(), groupId, user.getUserId(),
1161 Layout.class.getName(), importedLayout.getPlid(), false,
1162 addGroupPermissions, addGuestPermissions);
1163
1164 LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
1165 groupId, privateLayout);
1166
1167 importedLayout.setLayoutSet(layoutSet);
1168 }
1169 else {
1170 importedLayout = existingLayout;
1171 }
1172
1173 newLayoutsMap.put(oldLayoutId, importedLayout);
1174
1175 long parentLayoutId = layout.getParentLayoutId();
1176
1177 Node parentLayoutNode = rootElement.selectSingleNode(
1178 "./layouts/layout[@layout-id='" + parentLayoutId + "']");
1179
1180 String parentLayoutUuid = GetterUtil.getString(
1181 layoutElement.attributeValue("parent-layout-uuid"));
1182
1183 if ((parentLayoutId != LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) &&
1184 (parentLayoutNode != null)) {
1185
1186 importLayout(
1187 portletDataContext, user, layoutCache, previousLayouts,
1188 newLayouts, newLayoutsMap, portletsMergeMode, themeId,
1189 colorSchemeId, layoutsImportMode, privateLayout,
1190 importPermissions, importPublicLayoutPermissions,
1191 importThemeSettings, rootElement, (Element)parentLayoutNode);
1192
1193 Layout parentLayout = newLayoutsMap.get(parentLayoutId);
1194
1195 parentLayoutId = parentLayout.getLayoutId();
1196 }
1197 else if (Validator.isNotNull(parentLayoutUuid)) {
1198 Layout parentLayout =
1199 LayoutLocalServiceUtil.getLayoutByUuidAndGroupId(
1200 parentLayoutUuid, groupId, privateLayout);
1201
1202 parentLayoutId = parentLayout.getLayoutId();
1203 }
1204
1205 if (_log.isDebugEnabled()) {
1206 _log.debug(
1207 "Importing layout with layout id " + layoutId +
1208 " and parent layout id " + parentLayoutId);
1209 }
1210
1211 importedLayout.setCompanyId(user.getCompanyId());
1212 importedLayout.setParentLayoutId(parentLayoutId);
1213 importedLayout.setName(layout.getName());
1214 importedLayout.setTitle(layout.getTitle());
1215 importedLayout.setDescription(layout.getDescription());
1216 importedLayout.setKeywords(layout.getKeywords());
1217 importedLayout.setRobots(layout.getRobots());
1218 importedLayout.setType(layout.getType());
1219
1220 if (layout.isTypeArticle()) {
1221 importJournalArticle(portletDataContext, layout, layoutElement);
1222
1223 updateTypeSettings(importedLayout, layout);
1224 }
1225 else if (layout.isTypePortlet() &&
1226 Validator.isNotNull(layout.getTypeSettings()) &&
1227 !portletsMergeMode.equals(
1228 PortletDataHandlerKeys.PORTLETS_MERGE_MODE_REPLACE)) {
1229
1230 mergePortlets(
1231 importedLayout, layout.getTypeSettings(), portletsMergeMode);
1232 }
1233 else if (layout.isTypeLinkToLayout()) {
1234 UnicodeProperties typeSettingsProperties =
1235 layout.getTypeSettingsProperties();
1236
1237 long linkToLayoutId = GetterUtil.getLong(
1238 typeSettingsProperties.getProperty(
1239 "linkToLayoutId", StringPool.BLANK));
1240
1241 if (linkToLayoutId > 0) {
1242 Node linkedLayoutNode = rootElement.selectSingleNode(
1243 "./layouts/layout[@layout-id='" + linkToLayoutId + "']");
1244
1245 if (linkedLayoutNode != null) {
1246 importLayout(
1247 portletDataContext, user, layoutCache, previousLayouts,
1248 newLayouts, newLayoutsMap, portletsMergeMode, themeId,
1249 colorSchemeId, layoutsImportMode, privateLayout,
1250 importPermissions, importPublicLayoutPermissions,
1251 importThemeSettings, rootElement,
1252 (Element)linkedLayoutNode);
1253
1254 Layout linkedLayout = newLayoutsMap.get(linkToLayoutId);
1255
1256 typeSettingsProperties.setProperty(
1257 "privateLayout",
1258 String.valueOf(linkedLayout.isPrivateLayout()));
1259 typeSettingsProperties.setProperty(
1260 "linkToLayoutId",
1261 String.valueOf(linkedLayout.getLayoutId()));
1262 }
1263 else {
1264 if (_log.isWarnEnabled()) {
1265 StringBundler sb = new StringBundler();
1266
1267 sb.append("Unable to link layout with friendly URL ");
1268 sb.append(layout.getFriendlyURL());
1269 sb.append(" and layout id ");
1270 sb.append(layout.getLayoutId());
1271 sb.append(" to layout with layout id ");
1272 sb.append(linkToLayoutId);
1273
1274 _log.warn(sb.toString());
1275 }
1276 }
1277 }
1278
1279 updateTypeSettings(importedLayout, layout);
1280 }
1281 else {
1282 updateTypeSettings(importedLayout, layout);
1283 }
1284
1285 importedLayout.setHidden(layout.isHidden());
1286 importedLayout.setFriendlyURL(friendlyURL);
1287
1288 if (importThemeSettings) {
1289 importedLayout.setThemeId(layout.getThemeId());
1290 importedLayout.setColorSchemeId(layout.getColorSchemeId());
1291 }
1292 else {
1293 importedLayout.setThemeId(StringPool.BLANK);
1294 importedLayout.setColorSchemeId(StringPool.BLANK);
1295 }
1296
1297 importedLayout.setWapThemeId(layout.getWapThemeId());
1298 importedLayout.setWapColorSchemeId(layout.getWapColorSchemeId());
1299 importedLayout.setCss(layout.getCss());
1300 importedLayout.setPriority(layout.getPriority());
1301 importedLayout.setLayoutPrototypeUuid(layout.getLayoutPrototypeUuid());
1302 importedLayout.setLayoutPrototypeLinkEnabled(
1303 layout.isLayoutPrototypeLinkEnabled());
1304
1305 StagingUtil.updateLastImportSettings(
1306 layoutElement, importedLayout, portletDataContext);
1307
1308 fixTypeSettings(importedLayout);
1309
1310 importedLayout.setIconImage(false);
1311
1312 if (layout.isIconImage()) {
1313 String iconImagePath = layoutElement.elementText("icon-image-path");
1314
1315 byte[] iconBytes = portletDataContext.getZipEntryAsByteArray(
1316 iconImagePath);
1317
1318 if ((iconBytes != null) && (iconBytes.length > 0)) {
1319 importedLayout.setIconImage(true);
1320
1321 if (importedLayout.getIconImageId() == 0) {
1322 long iconImageId = CounterLocalServiceUtil.increment();
1323
1324 importedLayout.setIconImageId(iconImageId);
1325 }
1326
1327 ImageLocalServiceUtil.updateImage(
1328 importedLayout.getIconImageId(), iconBytes);
1329 }
1330 }
1331 else {
1332 ImageLocalServiceUtil.deleteImage(importedLayout.getIconImageId());
1333 }
1334
1335 ServiceContext serviceContext = portletDataContext.createServiceContext(
1336 layoutElement, importedLayout, null);
1337
1338 importedLayout.setExpandoBridgeAttributes(serviceContext);
1339
1340 LayoutUtil.update(importedLayout);
1341
1342 portletDataContext.setPlid(importedLayout.getPlid());
1343 portletDataContext.setOldPlid(layout.getPlid());
1344
1345 newLayouts.add(importedLayout);
1346
1347
1348
1349 if (importPermissions) {
1350 _permissionImporter.importLayoutPermissions(
1351 layoutCache, portletDataContext.getCompanyId(), groupId,
1352 user.getUserId(), importedLayout, layoutElement, rootElement);
1353 }
1354
1355 if (importPublicLayoutPermissions) {
1356 String resourceName = Layout.class.getName();
1357 String resourcePrimKey = String.valueOf(importedLayout.getPlid());
1358
1359 Role guestRole = RoleLocalServiceUtil.getRole(
1360 importedLayout.getCompanyId(), RoleConstants.GUEST);
1361
1362 ResourcePermissionLocalServiceUtil.setResourcePermissions(
1363 importedLayout.getCompanyId(), resourceName,
1364 ResourceConstants.SCOPE_INDIVIDUAL, resourcePrimKey,
1365 guestRole.getRoleId(), new String[] {ActionKeys.VIEW});
1366 }
1367
1368 _portletImporter.importPortletData(
1369 portletDataContext, PortletKeys.DOCKBAR, null, layoutElement);
1370 }
1371
1372 protected void importLayoutSetPrototype(
1373 PortletDataContext portletDataContext, User user,
1374 String layoutSetPrototypeUuid, ServiceContext serviceContext)
1375 throws PortalException, SystemException {
1376
1377 String path = getLayoutSetPrototypePath(
1378 portletDataContext, layoutSetPrototypeUuid);
1379
1380 LayoutSetPrototype layoutSetPrototype = null;
1381
1382 try {
1383 layoutSetPrototype =
1384 LayoutSetPrototypeLocalServiceUtil.
1385 getLayoutSetPrototypeByUuidAndCompanyId(
1386 layoutSetPrototypeUuid, serviceContext.getCompanyId());
1387 }
1388 catch (NoSuchLayoutSetPrototypeException nslspe) {
1389 }
1390
1391 if (layoutSetPrototype == null) {
1392 layoutSetPrototype =
1393 (LayoutSetPrototype)portletDataContext.getZipEntryAsObject(
1394 path.concat(".xml"));
1395
1396 serviceContext.setUuid(layoutSetPrototypeUuid);
1397
1398 layoutSetPrototype =
1399 LayoutSetPrototypeLocalServiceUtil.addLayoutSetPrototype(
1400 user.getUserId(), user.getCompanyId(),
1401 layoutSetPrototype.getNameMap(),
1402 layoutSetPrototype.getDescription(),
1403 layoutSetPrototype.getActive(), true, serviceContext);
1404 }
1405
1406 InputStream inputStream = portletDataContext.getZipEntryAsInputStream(
1407 path.concat(".lar"));
1408
1409 SitesUtil.importLayoutSetPrototype(
1410 layoutSetPrototype, inputStream, serviceContext);
1411 }
1412
1413 protected String importTheme(LayoutSet layoutSet, InputStream themeZip)
1414 throws Exception {
1415
1416 ThemeLoader themeLoader = ThemeLoaderFactory.getDefaultThemeLoader();
1417
1418 if (themeLoader == null) {
1419 _log.error("No theme loaders are deployed");
1420
1421 return null;
1422 }
1423
1424 ZipReader zipReader = ZipReaderFactoryUtil.getZipReader(themeZip);
1425
1426 String lookAndFeelXML = zipReader.getEntryAsString(
1427 "liferay-look-and-feel.xml");
1428
1429 String themeId = String.valueOf(layoutSet.getGroupId());
1430
1431 if (layoutSet.isPrivateLayout()) {
1432 themeId += "-private";
1433 }
1434 else {
1435 themeId += "-public";
1436 }
1437
1438 if (PropsValues.THEME_LOADER_NEW_THEME_ID_ON_IMPORT) {
1439 Date now = new Date();
1440
1441 themeId += "-" + Time.getShortTimestamp(now);
1442 }
1443
1444 String themeName = themeId;
1445
1446 lookAndFeelXML = StringUtil.replace(
1447 lookAndFeelXML,
1448 new String[] {
1449 "[$GROUP_ID$]", "[$THEME_ID$]", "[$THEME_NAME$]"
1450 },
1451 new String[] {
1452 String.valueOf(layoutSet.getGroupId()), themeId, themeName
1453 }
1454 );
1455
1456 FileUtil.deltree(
1457 themeLoader.getFileStorage() + StringPool.SLASH + themeId);
1458
1459 List<String> zipEntries = zipReader.getEntries();
1460
1461 for (String zipEntry : zipEntries) {
1462 String key = zipEntry;
1463
1464 if (key.equals("liferay-look-and-feel.xml")) {
1465 FileUtil.write(
1466 themeLoader.getFileStorage() + StringPool.SLASH + themeId +
1467 StringPool.SLASH + key,
1468 lookAndFeelXML.getBytes());
1469 }
1470 else {
1471 InputStream is = zipReader.getEntryAsInputStream(zipEntry);
1472
1473 FileUtil.write(
1474 themeLoader.getFileStorage() + StringPool.SLASH + themeId +
1475 StringPool.SLASH + key,
1476 is);
1477 }
1478 }
1479
1480 themeLoader.loadThemes();
1481
1482 ClusterRequest clusterRequest = ClusterRequest.createMulticastRequest(
1483 _loadThemesMethodHandler, true);
1484
1485 clusterRequest.setFireAndForget(true);
1486
1487 ClusterExecutorUtil.execute(clusterRequest);
1488
1489 themeId +=
1490 PortletConstants.WAR_SEPARATOR +
1491 themeLoader.getServletContextName();
1492
1493 return PortalUtil.getJsSafePortletId(themeId);
1494 }
1495
1496 protected void mergePortlets(
1497 Layout layout, String newTypeSettings, String portletsMergeMode) {
1498
1499 try {
1500 UnicodeProperties previousTypeSettingsProperties =
1501 layout.getTypeSettingsProperties();
1502
1503 LayoutTypePortlet previousLayoutType =
1504 (LayoutTypePortlet)layout.getLayoutType();
1505
1506 LayoutTemplate previousLayoutTemplate =
1507 previousLayoutType.getLayoutTemplate();
1508
1509 List<String> previousColumns = previousLayoutTemplate.getColumns();
1510
1511 UnicodeProperties newTypeSettingsProperties = new UnicodeProperties(
1512 true);
1513
1514 newTypeSettingsProperties.load(newTypeSettings);
1515
1516 String layoutTemplateId = newTypeSettingsProperties.getProperty(
1517 LayoutTypePortletConstants.LAYOUT_TEMPLATE_ID);
1518
1519 previousTypeSettingsProperties.setProperty(
1520 LayoutTypePortletConstants.LAYOUT_TEMPLATE_ID,
1521 layoutTemplateId);
1522
1523 String nestedColumnIds = newTypeSettingsProperties.getProperty(
1524 LayoutTypePortletConstants.NESTED_COLUMN_IDS);
1525
1526 if (Validator.isNotNull(nestedColumnIds)) {
1527 previousTypeSettingsProperties.setProperty(
1528 LayoutTypePortletConstants.NESTED_COLUMN_IDS,
1529 nestedColumnIds);
1530
1531 String[] nestedColumnIdsArray = StringUtil.split(
1532 nestedColumnIds);
1533
1534 for (String nestedColumnId : nestedColumnIdsArray) {
1535 String nestedColumnValue =
1536 newTypeSettingsProperties.getProperty(nestedColumnId);
1537
1538 previousTypeSettingsProperties.setProperty(
1539 nestedColumnId, nestedColumnValue);
1540 }
1541 }
1542
1543 LayoutTemplate newLayoutTemplate =
1544 LayoutTemplateLocalServiceUtil.getLayoutTemplate(
1545 layoutTemplateId, false, null);
1546
1547 String[] newPortletIds = new String[0];
1548
1549 for (String columnId : newLayoutTemplate.getColumns()) {
1550 String columnValue = newTypeSettingsProperties.getProperty(
1551 columnId);
1552
1553 String[] portletIds = StringUtil.split(columnValue);
1554
1555 if (!previousColumns.contains(columnId)) {
1556 newPortletIds = ArrayUtil.append(newPortletIds, portletIds);
1557 }
1558 else {
1559 String[] previousPortletIds = StringUtil.split(
1560 previousTypeSettingsProperties.getProperty(columnId));
1561
1562 portletIds = appendPortletIds(
1563 previousPortletIds, portletIds, portletsMergeMode);
1564
1565 previousTypeSettingsProperties.setProperty(
1566 columnId, StringUtil.merge(portletIds));
1567 }
1568 }
1569
1570
1571
1572 String columnId = previousColumns.get(0);
1573
1574 String[] portletIds = StringUtil.split(
1575 previousTypeSettingsProperties.getProperty(columnId));
1576
1577 appendPortletIds(portletIds, newPortletIds, portletsMergeMode);
1578
1579 previousTypeSettingsProperties.setProperty(
1580 columnId, StringUtil.merge(portletIds));
1581
1582 layout.setTypeSettings(previousTypeSettingsProperties.toString());
1583 }
1584 catch (IOException ioe) {
1585 layout.setTypeSettings(newTypeSettings);
1586 }
1587 }
1588
1589 protected void updateTypeSettings(Layout importedLayout, Layout layout)
1590 throws PortalException, SystemException {
1591
1592 LayoutTypePortlet importedLayoutType =
1593 (LayoutTypePortlet)importedLayout.getLayoutType();
1594
1595 List<String> importedPortletIds = importedLayoutType.getPortletIds();
1596
1597 LayoutTypePortlet layoutType =
1598 (LayoutTypePortlet)layout.getLayoutType();
1599
1600 importedPortletIds.removeAll(layoutType.getPortletIds());
1601
1602 if (!importedPortletIds.isEmpty()) {
1603 PortletLocalServiceUtil.deletePortlets(
1604 importedLayout.getCompanyId(),
1605 importedPortletIds.toArray(
1606 new String[importedPortletIds.size()]),
1607 importedLayout.getPlid());
1608 }
1609
1610 importedLayout.setTypeSettings(layout.getTypeSettings());
1611 }
1612
1613 protected void validateLayoutPrototypes(
1614 long companyId, Element layoutsElement,
1615 List<Element> layoutElements)
1616 throws Exception {
1617
1618 List<Tuple> missingLayoutPrototypes = new ArrayList<Tuple>();
1619
1620 String layoutSetPrototypeUuid = layoutsElement.attributeValue(
1621 "layout-set-prototype-uuid");
1622
1623 if (Validator.isNotNull(layoutSetPrototypeUuid)) {
1624 try {
1625 LayoutSetPrototypeLocalServiceUtil.
1626 getLayoutSetPrototypeByUuidAndCompanyId(
1627 layoutSetPrototypeUuid, companyId);
1628 }
1629 catch (NoSuchLayoutSetPrototypeException nlspe) {
1630 String layoutSetPrototypeName = layoutsElement.attributeValue(
1631 "layout-set-prototype-name");
1632
1633 missingLayoutPrototypes.add(
1634 new Tuple(
1635 LayoutSetPrototype.class.getName(),
1636 layoutSetPrototypeUuid, layoutSetPrototypeName));
1637 }
1638 }
1639
1640 for (Element layoutElement : layoutElements) {
1641 String layoutPrototypeUuid = GetterUtil.getString(
1642 layoutElement.attributeValue("layout-prototype-uuid"));
1643
1644 if (Validator.isNotNull(layoutPrototypeUuid)) {
1645 try {
1646 LayoutPrototypeLocalServiceUtil.
1647 getLayoutPrototypeByUuidAndCompanyId(
1648 layoutPrototypeUuid, companyId);
1649 }
1650 catch (NoSuchLayoutPrototypeException nslpe) {
1651 String layoutPrototypeName = GetterUtil.getString(
1652 layoutElement.attributeValue("layout-prototype-name"));
1653
1654 missingLayoutPrototypes.add(
1655 new Tuple(
1656 LayoutPrototype.class.getName(),
1657 layoutPrototypeUuid, layoutPrototypeName));
1658 }
1659 }
1660 }
1661
1662 if (!missingLayoutPrototypes.isEmpty()) {
1663 throw new LayoutPrototypeException(missingLayoutPrototypes);
1664 }
1665 }
1666
1667 private static Log _log = LogFactoryUtil.getLog(LayoutImporter.class);
1668
1669 private static MethodHandler _loadThemesMethodHandler = new MethodHandler(
1670 new MethodKey(ThemeLoaderFactory.class, "loadThemes"));
1671
1672 private PermissionImporter _permissionImporter = new PermissionImporter();
1673 private PortletImporter _portletImporter = new PortletImporter();
1674
1675 }