1
22
23 package com.liferay.portal.lar;
24
25 import com.liferay.counter.service.CounterLocalServiceUtil;
26 import com.liferay.portal.LARFileException;
27 import com.liferay.portal.LARTypeException;
28 import com.liferay.portal.LayoutImportException;
29 import com.liferay.portal.NoSuchLayoutException;
30 import com.liferay.portal.PortalException;
31 import com.liferay.portal.SystemException;
32 import com.liferay.portal.comm.CommLink;
33 import com.liferay.portal.kernel.log.Log;
34 import com.liferay.portal.kernel.log.LogFactoryUtil;
35 import com.liferay.portal.kernel.util.ArrayUtil;
36 import com.liferay.portal.kernel.util.FileUtil;
37 import com.liferay.portal.kernel.util.GetterUtil;
38 import com.liferay.portal.kernel.util.LocaleUtil;
39 import com.liferay.portal.kernel.util.MapUtil;
40 import com.liferay.portal.kernel.util.MethodWrapper;
41 import com.liferay.portal.kernel.util.ReleaseInfo;
42 import com.liferay.portal.kernel.util.StringPool;
43 import com.liferay.portal.kernel.util.StringUtil;
44 import com.liferay.portal.kernel.util.Time;
45 import com.liferay.portal.kernel.util.UnicodeProperties;
46 import com.liferay.portal.kernel.util.Validator;
47 import com.liferay.portal.kernel.xml.Document;
48 import com.liferay.portal.kernel.xml.DocumentException;
49 import com.liferay.portal.kernel.xml.Element;
50 import com.liferay.portal.kernel.xml.SAXReaderUtil;
51 import com.liferay.portal.kernel.zip.ZipReader;
52 import com.liferay.portal.model.Group;
53 import com.liferay.portal.model.GroupConstants;
54 import com.liferay.portal.model.Layout;
55 import com.liferay.portal.model.LayoutConstants;
56 import com.liferay.portal.model.LayoutSet;
57 import com.liferay.portal.model.LayoutTemplate;
58 import com.liferay.portal.model.LayoutTypePortlet;
59 import com.liferay.portal.model.Portlet;
60 import com.liferay.portal.model.PortletConstants;
61 import com.liferay.portal.model.Resource;
62 import com.liferay.portal.model.ResourceConstants;
63 import com.liferay.portal.model.Role;
64 import com.liferay.portal.model.User;
65 import com.liferay.portal.model.impl.ColorSchemeImpl;
66 import com.liferay.portal.model.impl.LayoutTypePortletImpl;
67 import com.liferay.portal.service.GroupLocalServiceUtil;
68 import com.liferay.portal.service.ImageLocalServiceUtil;
69 import com.liferay.portal.service.LayoutLocalServiceUtil;
70 import com.liferay.portal.service.LayoutSetLocalServiceUtil;
71 import com.liferay.portal.service.LayoutTemplateLocalServiceUtil;
72 import com.liferay.portal.service.PermissionLocalServiceUtil;
73 import com.liferay.portal.service.PortletLocalServiceUtil;
74 import com.liferay.portal.service.ResourcePermissionLocalServiceUtil;
75 import com.liferay.portal.service.RoleLocalServiceUtil;
76 import com.liferay.portal.service.permission.PortletPermissionUtil;
77 import com.liferay.portal.service.persistence.LayoutUtil;
78 import com.liferay.portal.service.persistence.UserUtil;
79 import com.liferay.portal.theme.ThemeLoader;
80 import com.liferay.portal.theme.ThemeLoaderFactory;
81 import com.liferay.portal.util.PortalUtil;
82 import com.liferay.portal.util.PortletKeys;
83 import com.liferay.portal.util.PropsValues;
84 import com.liferay.portlet.journal.model.JournalArticle;
85 import com.liferay.util.LocalizationUtil;
86
87 import java.io.ByteArrayInputStream;
88 import java.io.IOException;
89 import java.io.InputStream;
90
91 import java.util.ArrayList;
92 import java.util.Date;
93 import java.util.HashSet;
94 import java.util.Iterator;
95 import java.util.List;
96 import java.util.Locale;
97 import java.util.Map;
98 import java.util.Set;
99
100 import org.apache.commons.lang.time.StopWatch;
101
102
113 public class LayoutImporter {
114
115 public void importLayouts(
116 long userId, long groupId, boolean privateLayout,
117 Map<String, String[]> parameterMap, InputStream is)
118 throws PortalException, SystemException {
119
120 boolean deleteMissingLayouts = MapUtil.getBoolean(
121 parameterMap, PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
122 Boolean.TRUE.booleanValue());
123 boolean deletePortletData = MapUtil.getBoolean(
124 parameterMap, PortletDataHandlerKeys.DELETE_PORTLET_DATA);
125 boolean importPermissions = MapUtil.getBoolean(
126 parameterMap, PortletDataHandlerKeys.PERMISSIONS);
127 boolean importUserPermissions = MapUtil.getBoolean(
128 parameterMap, PortletDataHandlerKeys.PERMISSIONS);
129 boolean importPortletData = MapUtil.getBoolean(
130 parameterMap, PortletDataHandlerKeys.PORTLET_DATA);
131 boolean importPortletSetup = MapUtil.getBoolean(
132 parameterMap, PortletDataHandlerKeys.PORTLET_SETUP);
133 boolean importPortletArchivedSetups = MapUtil.getBoolean(
134 parameterMap, PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS);
135 boolean importPortletUserPreferences = MapUtil.getBoolean(
136 parameterMap, PortletDataHandlerKeys.PORTLET_USER_PREFERENCES);
137 boolean importTheme = MapUtil.getBoolean(
138 parameterMap, PortletDataHandlerKeys.THEME);
139 String layoutsImportMode = MapUtil.getString(
140 parameterMap, PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE,
141 PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_MERGE_BY_LAYOUT_ID);
142 String portletsMergeMode = MapUtil.getString(
143 parameterMap, PortletDataHandlerKeys.PORTLETS_MERGE_MODE,
144 PortletDataHandlerKeys.PORTLETS_MERGE_MODE_REPLACE);
145 String userIdStrategy = MapUtil.getString(
146 parameterMap, PortletDataHandlerKeys.USER_ID_STRATEGY);
147
148 if (_log.isDebugEnabled()) {
149 _log.debug("Delete portlet data " + deletePortletData);
150 _log.debug("Import permissions " + importPermissions);
151 _log.debug("Import user permissions " + importUserPermissions);
152 _log.debug("Import portlet data " + importPortletData);
153 _log.debug("Import portlet setup " + importPortletSetup);
154 _log.debug(
155 "Import portlet archived setups " +
156 importPortletArchivedSetups);
157 _log.debug(
158 "Import portlet user preferences " +
159 importPortletUserPreferences);
160 _log.debug("Import theme " + importTheme);
161 }
162
163 StopWatch stopWatch = null;
164
165 if (_log.isInfoEnabled()) {
166 stopWatch = new StopWatch();
167
168 stopWatch.start();
169 }
170
171 LayoutCache layoutCache = new LayoutCache();
172
173 LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
174 groupId, privateLayout);
175
176 long companyId = layoutSet.getCompanyId();
177
178 User user = UserUtil.findByPrimaryKey(userId);
179
180 UserIdStrategy strategy = _portletImporter.getUserIdStrategy(
181 user, userIdStrategy);
182
183 ZipReader zipReader = new ZipReader(is);
184
185 PortletDataContext context = new PortletDataContextImpl(
186 companyId, groupId, parameterMap, new HashSet<String>(), strategy,
187 zipReader);
188
189 Group guestGroup = GroupLocalServiceUtil.getGroup(
190 companyId, GroupConstants.GUEST);
191
192
194 Element root = null;
195 byte[] themeZip = null;
196
197
199 String xml = context.getZipEntryAsString("/manifest.xml");
200
201 if (xml == null) {
202 throw new LARFileException("manifest.xml not found in the LAR");
203 }
204
205 try {
206 Document doc = SAXReaderUtil.read(xml);
207
208 root = doc.getRootElement();
209 }
210 catch (Exception e) {
211 throw new LARFileException(e);
212 }
213
214
216 Element header = root.element("header");
217
218 int buildNumber = ReleaseInfo.getBuildNumber();
219
220 int importBuildNumber = GetterUtil.getInteger(
221 header.attributeValue("build-number"));
222
223 if (buildNumber != importBuildNumber) {
224 throw new LayoutImportException(
225 "LAR build number " + importBuildNumber + " does not match " +
226 "portal build number " + buildNumber);
227 }
228
229
231 String larType = header.attributeValue("type");
232
233 if (!larType.equals("layout-set")) {
234 throw new LARTypeException(
235 "Invalid type of LAR file (" + larType + ")");
236 }
237
238
240 long importGroupId = GetterUtil.getLong(
241 header.attributeValue("group-id"));
242
243 context.setImportGroupId(importGroupId);
244
245
247 if (importTheme) {
248 themeZip = context.getZipEntryAsByteArray("theme.zip");
249 }
250
251
253 String themeId = header.attributeValue("theme-id");
254 String colorSchemeId = header.attributeValue("color-scheme-id");
255
256 boolean useThemeZip = false;
257
258 if (themeZip != null) {
259 try {
260 String importThemeId = importTheme(layoutSet, themeZip);
261
262 if (importThemeId != null) {
263 themeId = importThemeId;
264 colorSchemeId =
265 ColorSchemeImpl.getDefaultRegularColorSchemeId();
266
267 useThemeZip = true;
268 }
269
270 if (_log.isDebugEnabled()) {
271 _log.debug(
272 "Importing theme takes " + stopWatch.getTime() + " ms");
273 }
274 }
275 catch (Exception e) {
276 throw new SystemException(e);
277 }
278 }
279
280 boolean wapTheme = false;
281
282 LayoutSetLocalServiceUtil.updateLookAndFeel(
283 groupId, privateLayout, themeId, colorSchemeId, StringPool.BLANK,
284 wapTheme);
285
286
289 _portletImporter.readComments(context, root);
290 _portletImporter.readRatings(context, root);
291 _portletImporter.readTags(context, root);
292
293
295 List<Layout> previousLayouts = LayoutUtil.findByG_P(
296 groupId, privateLayout);
297
298 List<Layout> newLayouts = new ArrayList<Layout>();
299
300 Set<Long> newLayoutIds = new HashSet<Long>();
301
302 Map<Long, Long> newLayoutIdPlidMap =
303 (Map<Long, Long>)context.getNewPrimaryKeysMap(Layout.class);
304
305 List<Element> layoutEls = root.element("layouts").elements("layout");
306
307 if (_log.isDebugEnabled()) {
308 if (layoutEls.size() > 0) {
309 _log.debug("Importing layouts");
310 }
311 }
312
313 for (Element layoutRefEl : layoutEls) {
314 long layoutId = GetterUtil.getInteger(
315 layoutRefEl.attributeValue("layout-id"));
316
317 long oldLayoutId = layoutId;
318
319 String layoutPath = layoutRefEl.attributeValue("path");
320
321 Element layoutEl = null;
322
323 try {
324 Document layoutDoc = SAXReaderUtil.read(
325 context.getZipEntryAsString(layoutPath));
326
327 layoutEl = layoutDoc.getRootElement();
328 }
329 catch (DocumentException de) {
330 throw new SystemException(de);
331 }
332
333 long parentLayoutId = GetterUtil.getInteger(
334 layoutEl.elementText("parent-layout-id"));
335
336 if (_log.isDebugEnabled()) {
337 _log.debug(
338 "Importing layout with layout id " + layoutId +
339 " and parent layout id " + parentLayoutId);
340 }
341
342 long oldPlid = GetterUtil.getInteger(
343 layoutEl.attributeValue("old-plid"));
344
345 String name = layoutEl.elementText("name");
346 String title = layoutEl.elementText("title");
347 String description = layoutEl.elementText("description");
348 String type = layoutEl.elementText("type");
349 String typeSettings = layoutEl.elementText("type-settings");
350 boolean hidden = GetterUtil.getBoolean(
351 layoutEl.elementText("hidden"));
352 String friendlyURL = layoutEl.elementText("friendly-url");
353 boolean iconImage = GetterUtil.getBoolean(
354 layoutEl.elementText("icon-image"));
355
356 byte[] iconBytes = null;
357
358 if (iconImage) {
359 String path = layoutEl.elementText("icon-image-path");
360
361 iconBytes = context.getZipEntryAsByteArray(path);
362 }
363
364 if (useThemeZip) {
365 themeId = StringPool.BLANK;
366 colorSchemeId = StringPool.BLANK;
367 }
368 else {
369 themeId = layoutEl.elementText("theme-id");
370 colorSchemeId = layoutEl.elementText("color-scheme-id");
371 }
372
373 String wapThemeId = layoutEl.elementText("wap-theme-id");
374 String wapColorSchemeId = layoutEl.elementText(
375 "wap-color-scheme-id");
376 String css = layoutEl.elementText("css");
377 int priority = GetterUtil.getInteger(
378 layoutEl.elementText("priority"));
379
380 Layout layout = null;
381
382 if (layoutsImportMode.equals(
383 PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_ADD_AS_NEW)) {
384
385 layoutId = LayoutLocalServiceUtil.getNextLayoutId(
386 groupId, privateLayout);
387 friendlyURL = StringPool.SLASH + layoutId;
388 }
389 else if (layoutsImportMode.equals(
390 PortletDataHandlerKeys.
391 LAYOUTS_IMPORT_MODE_MERGE_BY_LAYOUT_NAME)) {
392
393 Locale locale = LocaleUtil.getDefault();
394
395 String localizedName = LocalizationUtil.getLocalization(
396 name, LocaleUtil.toLanguageId(locale));
397
398 for (Layout curLayout : previousLayouts) {
399 if (curLayout.getName(locale).equals(localizedName)) {
400 layout = curLayout;
401
402 break;
403 }
404 }
405
406 if (layout == null) {
407 layoutId = LayoutLocalServiceUtil.getNextLayoutId(
408 groupId, privateLayout);
409 }
410 }
411 else {
412 layout = LayoutUtil.fetchByG_P_L(
413 groupId, privateLayout, layoutId);
414 }
415
416 if (_log.isDebugEnabled()) {
417 if (layout == null) {
418 _log.debug(
419 "Layout with {groupId=" + groupId + ",privateLayout=" +
420 privateLayout + ",layoutId=" + layoutId +
421 "} does not exist");
422 }
423 else {
424 _log.debug(
425 "Layout with {groupId=" + groupId + ",privateLayout=" +
426 privateLayout + ",layoutId=" + layoutId +
427 "} exists");
428 }
429 }
430
431 if (layout == null) {
432 long plid = CounterLocalServiceUtil.increment();
433
434 layout = LayoutUtil.create(plid);
435
436 layout.setGroupId(groupId);
437 layout.setPrivateLayout(privateLayout);
438 layout.setLayoutId(layoutId);
439 }
440
441 layout.setCompanyId(user.getCompanyId());
442 layout.setParentLayoutId(parentLayoutId);
443 layout.setName(name);
444 layout.setTitle(title);
445 layout.setDescription(description);
446 layout.setType(type);
447
448 if (layout.getType().equals(LayoutConstants.TYPE_PORTLET) &&
449 Validator.isNotNull(layout.getTypeSettings()) &&
450 !portletsMergeMode.equals(
451 PortletDataHandlerKeys.
452 PORTLETS_MERGE_MODE_REPLACE)) {
453 mergePortlets(layout, typeSettings, portletsMergeMode);
454 }
455 else {
456 layout.setTypeSettings(typeSettings);
457 }
458
459 layout.setHidden(hidden);
460 layout.setFriendlyURL(friendlyURL);
461
462 if (iconImage) {
463 layout.setIconImage(iconImage);
464
465 if (layout.isNew()) {
466 long iconImageId = CounterLocalServiceUtil.increment();
467
468 layout.setIconImageId(iconImageId);
469 }
470 }
471
472 layout.setThemeId(themeId);
473 layout.setColorSchemeId(colorSchemeId);
474 layout.setWapThemeId(wapThemeId);
475 layout.setWapColorSchemeId(wapColorSchemeId);
476 layout.setCss(css);
477 layout.setPriority(priority);
478
479 fixTypeSettings(layout);
480
481 LayoutUtil.update(layout, false);
482
483 if ((iconBytes != null) && (iconBytes.length > 0)) {
484 ImageLocalServiceUtil.updateImage(
485 layout.getIconImageId(), iconBytes);
486 }
487
488 context.setPlid(layout.getPlid());
489 context.setOldPlid(oldPlid);
490
491 newLayoutIdPlidMap.put(oldLayoutId, layout.getPlid());
492
493 newLayoutIds.add(layoutId);
494
495 newLayouts.add(layout);
496
497 Element permissionsEl = layoutEl.element("permissions");
498
499
501 if (importPermissions && (permissionsEl != null)) {
502 String resourceName = Layout.class.getName();
503 String resourcePrimKey = String.valueOf(layout.getPlid());
504
505 if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 5) {
506 importLayoutPermissions_5(
507 layoutCache, companyId, groupId, userId, resourceName,
508 resourcePrimKey, permissionsEl);
509 }
510 else if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) {
511 importLayoutPermissions_6(
512 layoutCache, companyId, groupId, userId, resourceName,
513 resourcePrimKey, permissionsEl);
514 }
515 else {
516 importLayoutPermissions_4(
517 layoutCache, companyId, groupId, guestGroup, layout,
518 resourceName, resourcePrimKey, permissionsEl,
519 importUserPermissions);
520 }
521 }
522
523 _portletImporter.importPortletData(
524 context, PortletKeys.LAYOUT_CONFIGURATION, null, layoutEl);
525 }
526
527 List<Element> portletEls = root.element("portlets").elements("portlet");
528
529
531 if (deletePortletData) {
532 if (_log.isDebugEnabled()) {
533 if (portletEls.size() > 0) {
534 _log.debug("Deleting portlet data");
535 }
536 }
537
538 for (Element portletRefEl : portletEls) {
539 String portletId = portletRefEl.attributeValue("portlet-id");
540 long layoutId = GetterUtil.getLong(
541 portletRefEl.attributeValue("layout-id"));
542 long plid = newLayoutIdPlidMap.get(layoutId);
543
544 context.setPlid(plid);
545
546 _portletImporter.deletePortletData(context, portletId, plid);
547 }
548 }
549
550
552 if (_log.isDebugEnabled()) {
553 if (portletEls.size() > 0) {
554 _log.debug("Importing portlets");
555 }
556 }
557
558 for (Element portletRefEl : portletEls) {
559 String portletPath = portletRefEl.attributeValue("path");
560 String portletId = portletRefEl.attributeValue("portlet-id");
561 long layoutId = GetterUtil.getLong(
562 portletRefEl.attributeValue("layout-id"));
563 long plid = newLayoutIdPlidMap.get(layoutId);
564 long oldPlid = GetterUtil.getLong(
565 portletRefEl.attributeValue("old-plid"));
566
567 Layout layout = LayoutUtil.findByPrimaryKey(plid);
568
569 context.setPlid(plid);
570 context.setOldPlid(oldPlid);
571
572 Element portletEl = null;
573
574 try {
575 Document portletDoc = SAXReaderUtil.read(
576 context.getZipEntryAsString(portletPath));
577
578 portletEl = portletDoc.getRootElement();
579 }
580 catch (DocumentException de) {
581 throw new SystemException(de);
582 }
583
584
589
591 _portletImporter.importPortletPreferences(
592 context, layoutSet.getCompanyId(), layout.getGroupId(),
593 layout.getPlid(), null, portletEl, importPortletSetup,
594 importPortletArchivedSetups, importPortletUserPreferences);
595
596
598 Element portletDataEl = portletEl.element("portlet-data");
599
600 if (importPortletData && portletDataEl != null) {
601 _portletImporter.importPortletData(
602 context, portletId, plid, portletDataEl);
603 }
604
605
607 Element permissionsEl = portletEl.element("permissions");
608
609 if (importPermissions && (permissionsEl != null)) {
610 if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 6) {
611 String resourceName = PortletConstants.getRootPortletId(
612 portletId);
613
614 String resourcePrimKey =
615 PortletPermissionUtil.getPrimaryKey(
616 layout.getPlid(), portletId);
617
618 importPortletPermissions_6(
619 layoutCache, companyId, groupId, userId, resourceName,
620 resourcePrimKey, permissionsEl);
621 }
622 else if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM == 5) {
623 String resourceName = PortletConstants.getRootPortletId(
624 portletId);
625
626 String resourcePrimKey =
627 PortletPermissionUtil.getPrimaryKey(
628 layout.getPlid(), portletId);
629
630 importPortletPermissions_5(
631 layoutCache, companyId, groupId, userId, resourceName,
632 resourcePrimKey, permissionsEl);
633 }
634 else {
635 importPortletPermissions_4(
636 layoutCache, companyId, groupId, guestGroup, layout,
637 permissionsEl, importUserPermissions);
638 }
639 }
640
641
643 _portletImporter.importPortletPreferences(
644 context, layoutSet.getCompanyId(), groupId, 0, null, portletEl,
645 importPortletSetup, importPortletArchivedSetups,
646 importPortletUserPreferences);
647
648 if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM < 5) {
649
650
652 Element rolesEl = portletEl.element("roles");
653
654 if (importPermissions && (rolesEl != null)) {
655 importPortletRoles(
656 layoutCache, companyId, groupId, portletEl);
657
658 importPortletRoles(
659 layoutCache, companyId, groupId, portletId, rolesEl);
660 }
661 }
662 }
663
664 if (PropsValues.PERMISSIONS_USER_CHECK_ALGORITHM < 5) {
665 Element rolesEl = root.element("roles");
666
667
669 if (importPermissions) {
670 importLayoutRoles(layoutCache, companyId, groupId, rolesEl);
671 }
672 }
673
674
676 if (deleteMissingLayouts) {
677 deleteMissingLayouts(
678 groupId, privateLayout, newLayoutIds, previousLayouts);
679 }
680
681
683 LayoutSetLocalServiceUtil.updatePageCount(groupId, privateLayout);
684
685 if (_log.isInfoEnabled()) {
686 _log.info("Importing layouts takes " + stopWatch.getTime() + " ms");
687 }
688
689
691 for (Layout layout : newLayouts) {
692 UnicodeProperties typeSettingsProperties =
693 layout.getTypeSettingsProperties();
694
695 String articleId = typeSettingsProperties.getProperty("article-id");
696
697 if (Validator.isNotNull(articleId)) {
698 Map<String, String> articleIds =
699 (Map<String, String>)context.getNewPrimaryKeysMap(
700 JournalArticle.class);
701
702 typeSettingsProperties.setProperty(
703 "article-id",
704 MapUtil.getString(articleIds, articleId, articleId));
705
706 LayoutUtil.update(layout, false);
707 }
708 }
709 }
710
711 protected void deleteMissingLayouts(
712 long groupId, boolean privateLayout, Set<Long> newLayoutIds,
713 List<Layout> previousLayouts)
714 throws PortalException, SystemException {
715
716
718 if (_log.isDebugEnabled()) {
719 if (newLayoutIds.size() > 0) {
720 _log.debug("Delete missing layouts");
721 }
722 }
723
724 for (Layout layout : previousLayouts) {
725 if (!newLayoutIds.contains(layout.getLayoutId())) {
726 try {
727 LayoutLocalServiceUtil.deleteLayout(layout, false);
728 }
729 catch (NoSuchLayoutException nsle) {
730 }
731 }
732 }
733
734
736 LayoutSetLocalServiceUtil.updatePageCount(groupId, privateLayout);
737 }
738
739 protected void fixTypeSettings(Layout layout) {
740 if (layout.getType().equals(LayoutConstants.TYPE_URL)) {
741 UnicodeProperties typeSettings = layout.getTypeSettingsProperties();
742
743 String url = GetterUtil.getString(typeSettings.getProperty("url"));
744
745 String friendlyURLPrivateGroupPath =
746 PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_GROUP_SERVLET_MAPPING;
747 String friendlyURLPrivateUserPath =
748 PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING;
749 String friendlyURLPublicPath =
750 PropsValues.LAYOUT_FRIENDLY_URL_PUBLIC_SERVLET_MAPPING;
751
752 if (url.startsWith(friendlyURLPrivateGroupPath) ||
753 url.startsWith(friendlyURLPrivateUserPath) ||
754 url.startsWith(friendlyURLPublicPath)) {
755
756 int x = url.indexOf(StringPool.SLASH, 1);
757
758 if (x > 0) {
759 int y = url.indexOf(StringPool.SLASH, x + 1);
760
761 if (y > x) {
762 String fixedUrl = url.substring(0, x) +
763
764 layout.getGroup().getFriendlyURL() +
765
766 url.substring(y);
767
768 typeSettings.setProperty("url", fixedUrl);
769 }
770 }
771 }
772 }
773 }
774
775 protected List<String> getActions(Element el) {
776 List<String> actions = new ArrayList<String>();
777
778 Iterator<Element> itr = el.elements("action-key").iterator();
779
780 while (itr.hasNext()) {
781 Element actionEl = itr.next();
782
783 actions.add(actionEl.getText());
784 }
785
786 return actions;
787 }
788
789 protected void importGroupPermissions(
790 LayoutCache layoutCache, long companyId, long groupId,
791 String resourceName, String resourcePrimKey, Element parentEl,
792 String elName, boolean portletActions)
793 throws PortalException, SystemException {
794
795 Element actionEl = parentEl.element(elName);
796
797 if (actionEl == null) {
798 return;
799 }
800
801 List<String> actions = getActions(actionEl);
802
803 Resource resource = layoutCache.getResource(
804 companyId, groupId, resourceName,
805 ResourceConstants.SCOPE_INDIVIDUAL, resourcePrimKey,
806 portletActions);
807
808 PermissionLocalServiceUtil.setGroupPermissions(
809 groupId, actions.toArray(new String[actions.size()]),
810 resource.getResourceId());
811 }
812
813 protected void importGroupRoles(
814 LayoutCache layoutCache, long companyId, long groupId,
815 String resourceName, String entityName,
816 Element parentEl)
817 throws PortalException, SystemException {
818
819 Element entityRolesEl = parentEl.element(entityName + "-roles");
820
821 if (entityRolesEl == null) {
822 return;
823 }
824
825 importRolePermissions(
826 layoutCache, companyId, resourceName, ResourceConstants.SCOPE_GROUP,
827 String.valueOf(groupId), entityRolesEl, true);
828 }
829
830 protected void importInheritedPermissions(
831 LayoutCache layoutCache, long companyId, String resourceName,
832 String resourcePrimKey, Element permissionsEl, String entityName,
833 boolean portletActions)
834 throws PortalException, SystemException {
835
836 Element entityPermissionsEl = permissionsEl.element(
837 entityName + "-permissions");
838
839 if (entityPermissionsEl == null) {
840 return;
841 }
842
843 List<Element> actionsEls = entityPermissionsEl.elements(
844 entityName + "-actions");
845
846 for (int i = 0; i < actionsEls.size(); i++) {
847 Element actionEl = actionsEls.get(i);
848
849 String name = actionEl.attributeValue("name");
850
851 long entityGroupId = layoutCache.getEntityGroupId(
852 companyId, entityName, name);
853
854 if (entityGroupId == 0) {
855 _log.warn(
856 "Ignore inherited permissions for entity " + entityName +
857 " with name " + name);
858 }
859 else {
860 Element parentEl = SAXReaderUtil.createElement("parent");
861
862 parentEl.add(actionEl.createCopy());
863
864 importGroupPermissions(
865 layoutCache, companyId, entityGroupId, resourceName,
866 resourcePrimKey, parentEl, entityName + "-actions",
867 portletActions);
868 }
869 }
870 }
871
872 protected void importInheritedRoles(
873 LayoutCache layoutCache, long companyId, long groupId,
874 String resourceName, String entityName, Element parentEl)
875 throws PortalException, SystemException {
876
877 Element entityRolesEl = parentEl.element(entityName + "-roles");
878
879 if (entityRolesEl == null) {
880 return;
881 }
882
883 List<Element> entityEls = entityRolesEl.elements(entityName);
884
885 for (int i = 0; i < entityEls.size(); i++) {
886 Element entityEl = entityEls.get(i);
887
888 String name = entityEl.attributeValue("name");
889
890 long entityGroupId = layoutCache.getEntityGroupId(
891 companyId, entityName, name);
892
893 if (entityGroupId == 0) {
894 _log.warn(
895 "Ignore inherited roles for entity " + entityName +
896 " with name " + name);
897 }
898 else {
899 importRolePermissions(
900 layoutCache, companyId, resourceName,
901 ResourceConstants.SCOPE_GROUP, String.valueOf(groupId),
902 entityEl, false);
903 }
904 }
905 }
906
907 protected void importLayoutPermissions_4(
908 LayoutCache layoutCache, long companyId, long groupId,
909 Group guestGroup, Layout layout, String resourceName,
910 String resourcePrimKey, Element permissionsEl,
911 boolean importUserPermissions)
912 throws PortalException, SystemException {
913
914 importGroupPermissions(
915 layoutCache, companyId, groupId, resourceName, resourcePrimKey,
916 permissionsEl, "community-actions", false);
917
918 if (groupId != guestGroup.getGroupId()) {
919 importGroupPermissions(
920 layoutCache, companyId, guestGroup.getGroupId(), resourceName,
921 resourcePrimKey, permissionsEl, "guest-actions", false);
922 }
923
924 if (importUserPermissions) {
925 importUserPermissions(
926 layoutCache, companyId, groupId, resourceName, resourcePrimKey,
927 permissionsEl, false);
928 }
929
930 importInheritedPermissions(
931 layoutCache, companyId, resourceName, resourcePrimKey,
932 permissionsEl, "organization", false);
933
934 importInheritedPermissions(
935 layoutCache, companyId, resourceName, resourcePrimKey,
936 permissionsEl, "location", false);
937
938 importInheritedPermissions(
939 layoutCache, companyId, resourceName, resourcePrimKey,
940 permissionsEl, "user-group", false);
941 }
942
943 protected void importLayoutPermissions_5(
944 LayoutCache layoutCache, long companyId, long groupId, long userId,
945 String resourceName, String resourcePrimKey, Element permissionsEl)
946 throws PortalException, SystemException {
947
948 boolean portletActions = false;
949
950 Resource resource = layoutCache.getResource(
951 companyId, groupId, resourceName,
952 ResourceConstants.SCOPE_INDIVIDUAL, resourcePrimKey,
953 portletActions);
954
955 importPermissions_5(
956 layoutCache, companyId, userId, resource.getResourceId(),
957 permissionsEl);
958 }
959
960 protected void importLayoutPermissions_6(
961 LayoutCache layoutCache, long companyId, long groupId, long userId,
962 String resourceName, String resourcePrimKey, Element permissionsEl)
963 throws PortalException, SystemException {
964
965 boolean portletActions = false;
966
967 importPermissions_6(
968 layoutCache, companyId, groupId, userId, resourceName,
969 resourcePrimKey, permissionsEl, portletActions);
970 }
971
972 protected void importLayoutRoles(
973 LayoutCache layoutCache, long companyId, long groupId,
974 Element rolesEl)
975 throws PortalException, SystemException {
976
977 String resourceName = Layout.class.getName();
978
979 importGroupRoles(
980 layoutCache, companyId, groupId, resourceName, "community",
981 rolesEl);
982
983 importUserRoles(layoutCache, companyId, groupId, resourceName, rolesEl);
984
985 importInheritedRoles(
986 layoutCache, companyId, groupId, resourceName, "organization",
987 rolesEl);
988
989 importInheritedRoles(
990 layoutCache, companyId, groupId, resourceName, "location", rolesEl);
991
992 importInheritedRoles(
993 layoutCache, companyId, groupId, resourceName, "user-group",
994 rolesEl);
995 }
996
997 protected void importPermissions_5(
998 LayoutCache layoutCache, long companyId, long userId,
999 long resourceId, Element permissionsEl)
1000 throws PortalException, SystemException {
1001
1002 List<Element> roleEls = permissionsEl.elements("role");
1003
1004 for (Element roleEl : roleEls) {
1005 String name = roleEl.attributeValue("name");
1006
1007 Role role = layoutCache.getRole(companyId, name);
1008
1009 if (role == null) {
1010 String description = roleEl.attributeValue("description");
1011 int type = Integer.valueOf(roleEl.attributeValue("type"));
1012
1013 role = RoleLocalServiceUtil.addRole(
1014 userId, companyId, name, description, type);
1015 }
1016
1017 List<String> actions = getActions(roleEl);
1018
1019 PermissionLocalServiceUtil.setRolePermissions(
1020 role.getRoleId(), actions.toArray(new String[actions.size()]),
1021 resourceId);
1022 }
1023 }
1024
1025 protected void importPermissions_6(
1026 LayoutCache layoutCache, long companyId, long groupId, long userId,
1027 String resourceName, String resourcePrimKey, Element permissionsEl,
1028 boolean portletActions)
1029 throws PortalException, SystemException {
1030
1031 List<Element> roleEls = permissionsEl.elements("role");
1032
1033 for (Element roleEl : roleEls) {
1034 String name = roleEl.attributeValue("name");
1035
1036 Role role = layoutCache.getRole(companyId, name);
1037
1038 if (role == null) {
1039 String description = roleEl.attributeValue("description");
1040 int type = Integer.valueOf(roleEl.attributeValue("type"));
1041
1042 role = RoleLocalServiceUtil.addRole(
1043 userId, companyId, name, description, type);
1044 }
1045
1046 List<String> actions = getActions(roleEl);
1047
1048 ResourcePermissionLocalServiceUtil.setResourcePermissions(
1049 companyId, resourceName, ResourceConstants.SCOPE_INDIVIDUAL,
1050 resourcePrimKey, role.getRoleId(),
1051 actions.toArray(new String[actions.size()]));
1052 }
1053 }
1054
1055 protected void importPortletPermissions_4(
1056 LayoutCache layoutCache, long companyId, long groupId,
1057 Group guestGroup, Layout layout, Element permissionsEl,
1058 boolean importUserPermissions)
1059 throws PortalException, SystemException {
1060
1061 Iterator<Element> itr = permissionsEl.elements("portlet").iterator();
1062
1063 while (itr.hasNext()) {
1064 Element portletEl = itr.next();
1065
1066 String portletId = portletEl.attributeValue("portlet-id");
1067
1068 String resourceName = PortletConstants.getRootPortletId(portletId);
1069 String resourcePrimKey = PortletPermissionUtil.getPrimaryKey(
1070 layout.getPlid(), portletId);
1071
1072 Portlet portlet = PortletLocalServiceUtil.getPortletById(
1073 companyId, resourceName);
1074
1075 if (portlet == null) {
1076 if (_log.isDebugEnabled()) {
1077 _log.debug(
1078 "Do not import portlet permissions for " + portletId +
1079 " because the portlet does not exist");
1080 }
1081 }
1082 else {
1083 importGroupPermissions(
1084 layoutCache, companyId, groupId, resourceName,
1085 resourcePrimKey, portletEl, "community-actions", true);
1086
1087 if (groupId != guestGroup.getGroupId()) {
1088 importGroupPermissions(
1089 layoutCache, companyId, guestGroup.getGroupId(),
1090 resourceName, resourcePrimKey, portletEl,
1091 "guest-actions", true);
1092 }
1093
1094 if (importUserPermissions) {
1095 importUserPermissions(
1096 layoutCache, companyId, groupId, resourceName,
1097 resourcePrimKey, portletEl, true);
1098 }
1099
1100 importInheritedPermissions(
1101 layoutCache, companyId, resourceName, resourcePrimKey,
1102 portletEl, "organization", true);
1103
1104 importInheritedPermissions(
1105 layoutCache, companyId, resourceName, resourcePrimKey,
1106 portletEl, "location", true);
1107
1108 importInheritedPermissions(
1109 layoutCache, companyId, resourceName, resourcePrimKey,
1110 portletEl, "user-group", true);
1111 }
1112 }
1113 }
1114
1115 protected void importPortletPermissions_5(
1116 LayoutCache layoutCache, long companyId, long groupId, long userId,
1117 String resourceName, String resourcePrimKey, Element permissionsEl)
1118 throws PortalException, SystemException {
1119
1120 boolean portletActions = true;
1121
1122 Resource resource = layoutCache.getResource(
1123 companyId, groupId, resourceName,
1124 ResourceConstants.SCOPE_INDIVIDUAL, resourcePrimKey,
1125 portletActions);
1126
1127 importPermissions_5(
1128 layoutCache, companyId, userId, resource.getResourceId(),
1129 permissionsEl);
1130 }
1131
1132 protected void importPortletPermissions_6(
1133 LayoutCache layoutCache, long companyId, long groupId, long userId,
1134 String resourceName, String resourcePrimKey, Element permissionsEl)
1135 throws PortalException, SystemException {
1136
1137 boolean portletActions = true;
1138
1139 importPermissions_6(
1140 layoutCache, companyId, groupId, userId, resourceName,
1141 resourcePrimKey, permissionsEl, portletActions);
1142 }
1143
1144 protected void importPortletRoles(
1145 LayoutCache layoutCache, long companyId, long groupId,
1146 String portletId, Element rolesEl)
1147 throws PortalException, SystemException {
1148
1149 String resourceName = PortletConstants.getRootPortletId(portletId);
1150
1151 Portlet portlet = PortletLocalServiceUtil.getPortletById(
1152 companyId, resourceName);
1153
1154 if (portlet == null) {
1155 if (_log.isDebugEnabled()) {
1156 _log.debug(
1157 "Do not import portlet roles for " + portletId +
1158 " because the portlet does not exist");
1159 }
1160 }
1161 else {
1162 importGroupRoles(
1163 layoutCache, companyId, groupId, resourceName, "community",
1164 rolesEl);
1165
1166 importUserRoles(
1167 layoutCache, companyId, groupId, resourceName, rolesEl);
1168
1169 importInheritedRoles(
1170 layoutCache, companyId, groupId, resourceName,
1171 "organization", rolesEl);
1172
1173 importInheritedRoles(
1174 layoutCache, companyId, groupId, resourceName, "location",
1175 rolesEl);
1176
1177 importInheritedRoles(
1178 layoutCache, companyId, groupId, resourceName, "user-group",
1179 rolesEl);
1180 }
1181 }
1182
1183 protected void importPortletRoles(
1184 LayoutCache layoutCache, long companyId, long groupId,
1185 Element rolesEl)
1186 throws PortalException, SystemException {
1187
1188 Iterator<Element> itr = rolesEl.elements("portlet").iterator();
1189
1190 while (itr.hasNext()) {
1191 Element portletEl = itr.next();
1192
1193 String portletId = portletEl.attributeValue("portlet-id");
1194
1195 String resourceName = PortletConstants.getRootPortletId(portletId);
1196
1197 Portlet portlet = PortletLocalServiceUtil.getPortletById(
1198 companyId, resourceName);
1199
1200 if (portlet == null) {
1201 if (_log.isDebugEnabled()) {
1202 _log.debug(
1203 "Do not import portlet roles for " + portletId +
1204 " because the portlet does not exist");
1205 }
1206 }
1207 else {
1208 importGroupRoles(
1209 layoutCache, companyId, groupId, resourceName, "community",
1210 portletEl);
1211
1212 importUserRoles(
1213 layoutCache, companyId, groupId, resourceName, portletEl);
1214
1215 importInheritedRoles(
1216 layoutCache, companyId, groupId, resourceName,
1217 "organization", portletEl);
1218
1219 importInheritedRoles(
1220 layoutCache, companyId, groupId, resourceName, "location",
1221 portletEl);
1222
1223 importInheritedRoles(
1224 layoutCache, companyId, groupId, resourceName, "user-group",
1225 portletEl);
1226 }
1227 }
1228 }
1229
1230 protected void importRolePermissions(
1231 LayoutCache layoutCache, long companyId, String resourceName,
1232 int scope, String resourcePrimKey, Element parentEl,
1233 boolean communityRole)
1234 throws PortalException, SystemException {
1235
1236 List<Element> roleEls = parentEl.elements("role");
1237
1238 for (int i = 0; i < roleEls.size(); i++) {
1239 Element roleEl = roleEls.get(i);
1240
1241 String roleName = roleEl.attributeValue("name");
1242
1243 Role role = layoutCache.getRole(companyId, roleName);
1244
1245 if (role == null) {
1246 _log.warn(
1247 "Ignoring permissions for role with name " + roleName);
1248 }
1249 else {
1250 List<String> actions = getActions(roleEl);
1251
1252 PermissionLocalServiceUtil.setRolePermissions(
1253 role.getRoleId(), companyId, resourceName, scope,
1254 resourcePrimKey,
1255 actions.toArray(new String[actions.size()]));
1256
1257 if (communityRole) {
1258 long[] groupIds = {GetterUtil.getLong(resourcePrimKey)};
1259
1260 GroupLocalServiceUtil.addRoleGroups(
1261 role.getRoleId(), groupIds);
1262 }
1263 }
1264 }
1265 }
1266
1267 protected String importTheme(LayoutSet layoutSet, byte[] themeZip)
1268 throws IOException {
1269
1270 ThemeLoader themeLoader = ThemeLoaderFactory.getDefaultThemeLoader();
1271
1272 if (themeLoader == null) {
1273 _log.error("No theme loaders are deployed");
1274
1275 return null;
1276 }
1277
1278 ZipReader zipReader = new ZipReader(new ByteArrayInputStream(themeZip));
1279
1280 Map<String, byte[]> entries = zipReader.getEntries();
1281
1282 String lookAndFeelXML = new String(
1283 entries.get("liferay-look-and-feel.xml"));
1284
1285 String themeId = String.valueOf(layoutSet.getGroupId());
1286
1287 if (layoutSet.isPrivateLayout()) {
1288 themeId += "-private";
1289 }
1290 else {
1291 themeId += "-public";
1292 }
1293
1294 if (PropsValues.THEME_LOADER_NEW_THEME_ID_ON_IMPORT) {
1295 Date now = new Date();
1296
1297 themeId += "-" + Time.getShortTimestamp(now);
1298 }
1299
1300 String themeName = themeId;
1301
1302 lookAndFeelXML = StringUtil.replace(
1303 lookAndFeelXML,
1304 new String[] {
1305 "[$GROUP_ID$]", "[$THEME_ID$]", "[$THEME_NAME$]"
1306 },
1307 new String[] {
1308 String.valueOf(layoutSet.getGroupId()), themeId, themeName
1309 }
1310 );
1311
1312 FileUtil.deltree(themeLoader.getFileStorage() + "/" + themeId);
1313
1314 Iterator<Map.Entry<String, byte[]>> itr = entries.entrySet().iterator();
1315
1316 while (itr.hasNext()) {
1317 Map.Entry<String, byte[]> entry = itr.next();
1318
1319 String key = entry.getKey();
1320 byte[] value = entry.getValue();
1321
1322 if (key.equals("liferay-look-and-feel.xml")) {
1323 value = lookAndFeelXML.getBytes();
1324 }
1325
1326 FileUtil.write(
1327 themeLoader.getFileStorage() + "/" + themeId + "/" + key,
1328 value);
1329 }
1330
1331 themeLoader.loadThemes();
1332
1333 CommLink commLink = CommLink.getInstance();
1334
1335 MethodWrapper methodWrapper = new MethodWrapper(
1336 ThemeLoaderFactory.class.getName(), "loadThemes");
1337
1338 commLink.send(methodWrapper);
1339
1340 themeId +=
1341 PortletConstants.WAR_SEPARATOR +
1342 themeLoader.getServletContextName();
1343
1344 return PortalUtil.getJsSafePortletId(themeId);
1345 }
1346
1347 protected void importUserPermissions(
1348 LayoutCache layoutCache, long companyId, long groupId,
1349 String resourceName, String resourcePrimKey, Element parentEl,
1350 boolean portletActions)
1351 throws PortalException, SystemException {
1352
1353 Element userPermissionsEl = parentEl.element("user-permissions");
1354
1355 if (userPermissionsEl == null) {
1356 return;
1357 }
1358
1359 List<Element> userActionsEls = userPermissionsEl.elements(
1360 "user-actions");
1361
1362 for (int i = 0; i < userActionsEls.size(); i++) {
1363 Element userActionsEl = userActionsEls.get(i);
1364
1365 String emailAddress = userActionsEl.attributeValue("email-address");
1366
1367 User user = layoutCache.getUser(companyId, groupId, emailAddress);
1368
1369 if (user == null) {
1370 if (_log.isWarnEnabled()) {
1371 _log.warn(
1372 "Ignoring permissions for user with email address " +
1373 emailAddress);
1374 }
1375 }
1376 else {
1377 List<String> actions = getActions(userActionsEl);
1378
1379 Resource resource = layoutCache.getResource(
1380 companyId, groupId, resourceName,
1381 ResourceConstants.SCOPE_INDIVIDUAL, resourcePrimKey,
1382 portletActions);
1383
1384 PermissionLocalServiceUtil.setUserPermissions(
1385 user.getUserId(),
1386 actions.toArray(new String[actions.size()]),
1387 resource.getResourceId());
1388 }
1389 }
1390 }
1391
1392 protected void importUserRoles(
1393 LayoutCache layoutCache, long companyId, long groupId,
1394 String resourceName, Element parentEl)
1395 throws PortalException, SystemException {
1396
1397 Element userRolesEl = parentEl.element("user-roles");
1398
1399 if (userRolesEl == null) {
1400 return;
1401 }
1402
1403 List<Element> userEls = userRolesEl.elements("user");
1404
1405 for (int i = 0; i < userEls.size(); i++) {
1406 Element userEl = userEls.get(i);
1407
1408 String emailAddress = userEl.attributeValue("email-address");
1409
1410 User user = layoutCache.getUser(companyId, groupId, emailAddress);
1411
1412 if (user == null) {
1413 if (_log.isWarnEnabled()) {
1414 _log.warn(
1415 "Ignoring roles for user with email address " +
1416 emailAddress);
1417 }
1418 }
1419 else {
1420 importRolePermissions(
1421 layoutCache, companyId, resourceName,
1422 ResourceConstants.SCOPE_GROUP, String.valueOf(groupId),
1423 userEl, false);
1424 }
1425 }
1426 }
1427
1428 protected void mergePortlets(
1429 Layout layout, String newTypeSettings, String portletsMergeMode) {
1430
1431 try {
1432 UnicodeProperties previousProps =
1433 layout.getTypeSettingsProperties();
1434 LayoutTypePortlet previousLayoutType =
1435 (LayoutTypePortlet)layout.getLayoutType();
1436 List<String> previousColumns =
1437 previousLayoutType.getLayoutTemplate().getColumns();
1438
1439 UnicodeProperties newProps = new UnicodeProperties(true);
1440
1441 newProps.load(newTypeSettings);
1442
1443 String layoutTemplateId = newProps.getProperty(
1444 LayoutTypePortletImpl.LAYOUT_TEMPLATE_ID);
1445
1446 LayoutTemplate newLayoutTemplate =
1447 LayoutTemplateLocalServiceUtil.getLayoutTemplate(
1448 layoutTemplateId, false, null);
1449
1450 String[] lostPortletIds = new String[0];
1451
1452 for (String columnId : newLayoutTemplate.getColumns()) {
1453 String columnValue =
1454 newProps.getProperty(columnId);
1455
1456 String[] portletIds = StringUtil.split(columnValue);
1457
1458 if (!previousColumns.contains(columnId)) {
1459 lostPortletIds = ArrayUtil.append(
1460 lostPortletIds, portletIds);
1461 }
1462 else {
1463
1464 String[] previousPortletIds = StringUtil.split(
1465 previousProps.getProperty(columnId));
1466
1467 portletIds = appendPortletIds(
1468 previousPortletIds, portletIds, portletsMergeMode);
1469
1470 previousProps.setProperty(
1471 columnId, StringUtil.merge(portletIds));
1472 }
1473 }
1474
1475
1477 String columnId = previousColumns.get(0);
1478
1479 String[] portletIds = StringUtil.split(
1480 previousProps.getProperty(columnId));
1481
1482 appendPortletIds(portletIds, lostPortletIds, portletsMergeMode);
1483
1484 previousProps.setProperty(
1485 columnId, StringUtil.merge(portletIds));
1486
1487 layout.setTypeSettings(previousProps.toString());
1488
1489 }
1490 catch (IOException e) {
1491 layout.setTypeSettings(newTypeSettings);
1492 }
1493 }
1494
1495 protected String[] appendPortletIds(
1496 String[] portletIds, String[] newPortletIds,
1497 String portletsMergeMode) {
1498
1499 for (String portletId : newPortletIds) {
1500 if (ArrayUtil.contains(portletIds, portletId)) {
1501 continue;
1502 }
1503
1504 if (portletsMergeMode.equals(
1505 PortletDataHandlerKeys.PORTLETS_MERGE_MODE_ADD_TO_BOTTOM)) {
1506 portletIds = ArrayUtil.append(
1507 portletIds, portletId);
1508 }
1509 else {
1510 portletIds = ArrayUtil.append(
1511 new String[] {portletId}, portletIds);
1512 }
1513 }
1514
1515 return portletIds;
1516 }
1517
1518 private static Log _log = LogFactoryUtil.getLog(LayoutImporter.class);
1519
1520 private PortletImporter _portletImporter = new PortletImporter();
1521
1522}