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