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