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