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