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