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