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.lar.PortletDataContext;
34 import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
35 import com.liferay.portal.kernel.lar.UserIdStrategy;
36 import com.liferay.portal.kernel.util.ArrayUtil;
37 import com.liferay.portal.kernel.util.FileUtil;
38 import com.liferay.portal.kernel.util.GetterUtil;
39 import com.liferay.portal.kernel.util.LocaleUtil;
40 import com.liferay.portal.kernel.util.MethodWrapper;
41 import com.liferay.portal.kernel.util.ReleaseInfo;
42 import com.liferay.portal.kernel.util.StringPool;
43 import com.liferay.portal.kernel.util.StringUtil;
44 import com.liferay.portal.kernel.util.Time;
45 import com.liferay.portal.kernel.util.UnicodeProperties;
46 import com.liferay.portal.kernel.util.Validator;
47 import com.liferay.portal.kernel.zip.ZipReader;
48 import com.liferay.portal.model.Group;
49 import com.liferay.portal.model.Layout;
50 import com.liferay.portal.model.LayoutConstants;
51 import com.liferay.portal.model.LayoutSet;
52 import com.liferay.portal.model.LayoutTemplate;
53 import com.liferay.portal.model.LayoutTypePortlet;
54 import com.liferay.portal.model.Portlet;
55 import com.liferay.portal.model.PortletConstants;
56 import com.liferay.portal.model.Resource;
57 import com.liferay.portal.model.ResourceConstants;
58 import com.liferay.portal.model.Role;
59 import com.liferay.portal.model.User;
60 import com.liferay.portal.model.impl.ColorSchemeImpl;
61 import com.liferay.portal.model.impl.GroupImpl;
62 import com.liferay.portal.model.impl.LayoutTypePortletImpl;
63 import com.liferay.portal.service.GroupLocalServiceUtil;
64 import com.liferay.portal.service.ImageLocalServiceUtil;
65 import com.liferay.portal.service.LayoutLocalServiceUtil;
66 import com.liferay.portal.service.LayoutSetLocalServiceUtil;
67 import com.liferay.portal.service.LayoutTemplateLocalServiceUtil;
68 import com.liferay.portal.service.PermissionLocalServiceUtil;
69 import com.liferay.portal.service.PortletLocalServiceUtil;
70 import com.liferay.portal.service.permission.PortletPermissionUtil;
71 import com.liferay.portal.service.persistence.LayoutUtil;
72 import com.liferay.portal.service.persistence.UserUtil;
73 import com.liferay.portal.theme.ThemeLoader;
74 import com.liferay.portal.theme.ThemeLoaderFactory;
75 import com.liferay.portal.util.DocumentUtil;
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 import org.dom4j.Document;
100 import org.dom4j.DocumentException;
101 import org.dom4j.DocumentHelper;
102 import org.dom4j.Element;
103
104
115 public class LayoutImporter {
116
117 public void importLayouts(
118 long userId, long groupId, boolean privateLayout,
119 Map<String, String[]> parameterMap, InputStream is)
120 throws PortalException, SystemException {
121
122 boolean deleteMissingLayouts = MapUtil.getBoolean(
123 parameterMap, PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
124 Boolean.TRUE.booleanValue());
125 boolean deletePortletData = MapUtil.getBoolean(
126 parameterMap, PortletDataHandlerKeys.DELETE_PORTLET_DATA);
127 boolean importPermissions = MapUtil.getBoolean(
128 parameterMap, PortletDataHandlerKeys.PERMISSIONS);
129 boolean importUserPermissions = MapUtil.getBoolean(
130 parameterMap, PortletDataHandlerKeys.PERMISSIONS);
131 boolean importPortletData = MapUtil.getBoolean(
132 parameterMap, PortletDataHandlerKeys.PORTLET_DATA);
133 boolean importPortletSetup = MapUtil.getBoolean(
134 parameterMap, PortletDataHandlerKeys.PORTLET_SETUP);
135 boolean importPortletArchivedSetups = MapUtil.getBoolean(
136 parameterMap, PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS);
137 boolean importPortletUserPreferences = MapUtil.getBoolean(
138 parameterMap, PortletDataHandlerKeys.PORTLET_USER_PREFERENCES);
139 boolean importTheme = MapUtil.getBoolean(
140 parameterMap, PortletDataHandlerKeys.THEME);
141 String layoutsImportMode = MapUtil.getString(
142 parameterMap, PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE,
143 PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_MERGE_BY_LAYOUT_ID);
144 String portletsMergeMode = MapUtil.getString(
145 parameterMap, PortletDataHandlerKeys.PORTLETS_MERGE_MODE,
146 PortletDataHandlerKeys.PORTLETS_MERGE_MODE_REPLACE);
147 String userIdStrategy = MapUtil.getString(
148 parameterMap, PortletDataHandlerKeys.USER_ID_STRATEGY);
149
150 if (_log.isDebugEnabled()) {
151 _log.debug("Delete portlet data " + deletePortletData);
152 _log.debug("Import permissions " + importPermissions);
153 _log.debug("Import user permissions " + importUserPermissions);
154 _log.debug("Import portlet data " + importPortletData);
155 _log.debug("Import portlet setup " + importPortletSetup);
156 _log.debug(
157 "Import portlet archived setups " +
158 importPortletArchivedSetups);
159 _log.debug(
160 "Import portlet user preferences " +
161 importPortletUserPreferences);
162 _log.debug("Import theme " + importTheme);
163 }
164
165 StopWatch stopWatch = null;
166
167 if (_log.isInfoEnabled()) {
168 stopWatch = new StopWatch();
169
170 stopWatch.start();
171 }
172
173 LayoutCache layoutCache = new LayoutCache();
174
175 LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
176 groupId, privateLayout);
177
178 long companyId = layoutSet.getCompanyId();
179
180 User user = UserUtil.findByPrimaryKey(userId);
181
182 UserIdStrategy strategy = _portletImporter.getUserIdStrategy(
183 user, userIdStrategy);
184
185 ZipReader zipReader = new ZipReader(is);
186
187 PortletDataContext context = new PortletDataContextImpl(
188 companyId, groupId, parameterMap, new HashSet(), strategy,
189 zipReader);
190
191 Group guestGroup = GroupLocalServiceUtil.getGroup(
192 companyId, GroupImpl.GUEST);
193
194
196 Element root = null;
197 byte[] themeZip = null;
198
199
201 String xml = context.getZipEntryAsString("/manifest.xml");
202
203 try {
204 Document doc = DocumentUtil.readDocumentFromXML(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 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 = DocumentUtil.readDocumentFromXML(
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) {
490 importLayoutPermissions(
491 layoutCache, companyId, groupId, guestGroup, layout,
492 permissionsEl, importUserPermissions);
493 }
494
495 _portletImporter.importPortletData(
496 context, PortletKeys.LAYOUT_CONFIGURATION, null, layoutEl);
497 }
498
499 List<Element> portletEls = root.element("portlets").elements("portlet");
500
501
503 if (deletePortletData) {
504 if (_log.isDebugEnabled()) {
505 if (portletEls.size() > 0) {
506 _log.debug("Deleting portlet data");
507 }
508 }
509
510 for (Element portletRefEl : portletEls) {
511 String portletId = portletRefEl.attributeValue("portlet-id");
512 long layoutId = GetterUtil.getLong(
513 portletRefEl.attributeValue("layout-id"));
514 long plid = newLayoutIdPlidMap.get(layoutId);
515
516 context.setPlid(plid);
517
518 _portletImporter.deletePortletData(context, portletId, plid);
519 }
520 }
521
522
524 if (_log.isDebugEnabled()) {
525 if (portletEls.size() > 0) {
526 _log.debug("Importing portlets");
527 }
528 }
529
530 for (Element portletRefEl : portletEls) {
531 String portletPath = portletRefEl.attributeValue("path");
532 String portletId = portletRefEl.attributeValue("portlet-id");
533 long layoutId = GetterUtil.getLong(
534 portletRefEl.attributeValue("layout-id"));
535 long plid = newLayoutIdPlidMap.get(layoutId);
536
537 Layout layout = LayoutUtil.findByPrimaryKey(plid);
538
539 context.setPlid(plid);
540
541 Element portletEl = null;
542
543 try {
544 Document portletDoc = DocumentUtil.readDocumentFromXML(
545 context.getZipEntryAsString(portletPath));
546
547 portletEl = portletDoc.getRootElement();
548 }
549 catch (DocumentException de) {
550 throw new SystemException(de);
551 }
552
553
558
560 _portletImporter.importPortletPreferences(
561 context, layoutSet.getCompanyId(), layout.getGroupId(),
562 layout.getPlid(), null, portletEl, importPortletSetup,
563 importPortletArchivedSetups, importPortletUserPreferences);
564
565
567 Element portletDataEl = portletEl.element("portlet-data");
568
569 if (importPortletData && portletDataEl != null) {
570 _portletImporter.importPortletData(
571 context, portletId, plid, portletDataEl);
572 }
573
574
576 Element permissionsEl = portletEl.element("permissions");
577
578 if (importPermissions) {
579 importPortletPermissions(
580 layoutCache, companyId, groupId, guestGroup, layout,
581 permissionsEl, importUserPermissions);
582 }
583
584
586 _portletImporter.importPortletPreferences(
587 context, layoutSet.getCompanyId(), groupId, 0, null, portletEl,
588 importPortletSetup, importPortletArchivedSetups,
589 importPortletUserPreferences);
590
591
593 Element rolesEl = portletEl.element("roles");
594
595 if (importPermissions) {
596 importPortletRoles(layoutCache, companyId, groupId, portletEl);
597 importPortletRoles(
598 layoutCache, companyId, groupId, portletId, rolesEl);
599 }
600 }
601
602 Element rolesEl = root.element("roles");
603
604
606 if (importPermissions) {
607 importLayoutRoles(layoutCache, companyId, groupId, rolesEl);
608 }
609
610
612 if (deleteMissingLayouts) {
613 deleteMissingLayouts(
614 groupId, privateLayout, newLayoutIds, previousLayouts);
615 }
616
617
619 LayoutSetLocalServiceUtil.updatePageCount(groupId, privateLayout);
620
621 if (_log.isInfoEnabled()) {
622 _log.info("Importing layouts takes " + stopWatch.getTime() + " ms");
623 }
624 }
625
626 protected void deleteMissingLayouts(
627 long groupId, boolean privateLayout, Set<Long> newLayoutIds,
628 List<Layout> previousLayouts)
629 throws PortalException, SystemException {
630
631
633 if (_log.isDebugEnabled()) {
634 if (newLayoutIds.size() > 0) {
635 _log.debug("Delete missing layouts");
636 }
637 }
638
639 for (Layout layout : previousLayouts) {
640 if (!newLayoutIds.contains(layout.getLayoutId())) {
641 try {
642 LayoutLocalServiceUtil.deleteLayout(layout, false);
643 }
644 catch (NoSuchLayoutException nsle) {
645 }
646 }
647 }
648
649
651 LayoutSetLocalServiceUtil.updatePageCount(groupId, privateLayout);
652 }
653
654 protected void fixTypeSettings(Layout layout) {
655 if (layout.getType().equals(LayoutConstants.TYPE_URL)) {
656 UnicodeProperties typeSettings = layout.getTypeSettingsProperties();
657
658 String url = GetterUtil.getString(typeSettings.getProperty("url"));
659
660 String friendlyURLPrivateGroupPath =
661 PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_GROUP_SERVLET_MAPPING;
662 String friendlyURLPrivateUserPath =
663 PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING;
664 String friendlyURLPublicPath =
665 PropsValues.LAYOUT_FRIENDLY_URL_PUBLIC_SERVLET_MAPPING;
666
667 if (url.startsWith(friendlyURLPrivateGroupPath) ||
668 url.startsWith(friendlyURLPrivateUserPath) ||
669 url.startsWith(friendlyURLPublicPath)) {
670
671 int x = url.indexOf(StringPool.SLASH, 1);
672
673 if (x > 0) {
674 int y = url.indexOf(StringPool.SLASH, x + 1);
675
676 if (y > x) {
677 String fixedUrl = url.substring(0, x) +
678
679 layout.getGroup().getFriendlyURL() +
680
681 url.substring(y);
682
683 typeSettings.setProperty("url", fixedUrl);
684 }
685 }
686 }
687 }
688 }
689
690 protected List<String> getActions(Element el) {
691 List<String> actions = new ArrayList<String>();
692
693 Iterator<Element> itr = el.elements("action-key").iterator();
694
695 while (itr.hasNext()) {
696 Element actionEl = itr.next();
697
698 actions.add(actionEl.getText());
699 }
700
701 return actions;
702 }
703
704 protected void importGroupPermissions(
705 LayoutCache layoutCache, long companyId, long groupId,
706 String resourceName, String resourcePrimKey, Element parentEl,
707 String elName, boolean portletActions)
708 throws PortalException, SystemException {
709
710 Element actionEl = parentEl.element(elName);
711
712 if (actionEl == null) {
713 return;
714 }
715
716 List<String> actions = getActions(actionEl);
717
718 Resource resource = layoutCache.getResource(
719 companyId, groupId, resourceName,
720 ResourceConstants.SCOPE_INDIVIDUAL, resourcePrimKey,
721 portletActions);
722
723 PermissionLocalServiceUtil.setGroupPermissions(
724 groupId, actions.toArray(new String[actions.size()]),
725 resource.getResourceId());
726 }
727
728 protected void importGroupRoles(
729 LayoutCache layoutCache, long companyId, long groupId,
730 String resourceName, String entityName,
731 Element parentEl)
732 throws PortalException, SystemException {
733
734 Element entityRolesEl = parentEl.element(entityName + "-roles");
735
736 if (entityRolesEl == null) {
737 return;
738 }
739
740 importRolePermissions(
741 layoutCache, companyId, resourceName, ResourceConstants.SCOPE_GROUP,
742 String.valueOf(groupId), entityRolesEl, true);
743 }
744
745 protected void importInheritedPermissions(
746 LayoutCache layoutCache, long companyId, String resourceName,
747 String resourcePrimKey, Element permissionsEl, String entityName,
748 boolean portletActions)
749 throws PortalException, SystemException {
750
751 Element entityPermissionsEl = permissionsEl.element(
752 entityName + "-permissions");
753
754 if (entityPermissionsEl == null) {
755 return;
756 }
757
758 List<Element> actionsEls = entityPermissionsEl.elements(
759 entityName + "-actions");
760
761 for (int i = 0; i < actionsEls.size(); i++) {
762 Element actionEl = actionsEls.get(i);
763
764 String name = actionEl.attributeValue("name");
765
766 long entityGroupId = layoutCache.getEntityGroupId(
767 companyId, entityName, name);
768
769 if (entityGroupId == 0) {
770 _log.warn(
771 "Ignore inherited permissions for entity " + entityName +
772 " with name " + name);
773 }
774 else {
775 Element parentEl = DocumentHelper.createElement("parent");
776
777 parentEl.add(actionEl.createCopy());
778
779 importGroupPermissions(
780 layoutCache, companyId, entityGroupId, resourceName,
781 resourcePrimKey, parentEl, entityName + "-actions",
782 portletActions);
783 }
784 }
785 }
786
787 protected void importInheritedRoles(
788 LayoutCache layoutCache, long companyId, long groupId,
789 String resourceName, String entityName, Element parentEl)
790 throws PortalException, SystemException {
791
792 Element entityRolesEl = parentEl.element(entityName + "-roles");
793
794 if (entityRolesEl == null) {
795 return;
796 }
797
798 List<Element> entityEls = entityRolesEl.elements(entityName);
799
800 for (int i = 0; i < entityEls.size(); i++) {
801 Element entityEl = entityEls.get(i);
802
803 String name = entityEl.attributeValue("name");
804
805 long entityGroupId = layoutCache.getEntityGroupId(
806 companyId, entityName, name);
807
808 if (entityGroupId == 0) {
809 _log.warn(
810 "Ignore inherited roles for entity " + entityName +
811 " with name " + name);
812 }
813 else {
814 importRolePermissions(
815 layoutCache, companyId, resourceName,
816 ResourceConstants.SCOPE_GROUP, String.valueOf(groupId),
817 entityEl, false);
818 }
819 }
820 }
821
822 protected void importLayoutPermissions(
823 LayoutCache layoutCache, long companyId, long groupId,
824 Group guestGroup, Layout layout, Element permissionsEl,
825 boolean importUserPermissions)
826 throws PortalException, SystemException {
827
828 String resourceName = Layout.class.getName();
829 String resourcePrimKey = String.valueOf(layout.getPlid());
830
831 importGroupPermissions(
832 layoutCache, companyId, groupId, resourceName, resourcePrimKey,
833 permissionsEl, "community-actions", false);
834
835 if (groupId != guestGroup.getGroupId()) {
836 importGroupPermissions(
837 layoutCache, companyId, guestGroup.getGroupId(), resourceName,
838 resourcePrimKey, permissionsEl, "guest-actions", false);
839 }
840
841 if (importUserPermissions) {
842 importUserPermissions(
843 layoutCache, companyId, groupId, resourceName, resourcePrimKey,
844 permissionsEl, false);
845 }
846
847 importInheritedPermissions(
848 layoutCache, companyId, resourceName, resourcePrimKey,
849 permissionsEl, "organization", false);
850
851 importInheritedPermissions(
852 layoutCache, companyId, resourceName, resourcePrimKey,
853 permissionsEl, "location", false);
854
855 importInheritedPermissions(
856 layoutCache, companyId, resourceName, resourcePrimKey,
857 permissionsEl, "user-group", false);
858 }
859
860 protected void importLayoutRoles(
861 LayoutCache layoutCache, long companyId, long groupId,
862 Element rolesEl)
863 throws PortalException, SystemException {
864
865 String resourceName = Layout.class.getName();
866
867 importGroupRoles(
868 layoutCache, companyId, groupId, resourceName, "community",
869 rolesEl);
870
871 importUserRoles(layoutCache, companyId, groupId, resourceName, rolesEl);
872
873 importInheritedRoles(
874 layoutCache, companyId, groupId, resourceName, "organization",
875 rolesEl);
876
877 importInheritedRoles(
878 layoutCache, companyId, groupId, resourceName, "location", rolesEl);
879
880 importInheritedRoles(
881 layoutCache, companyId, groupId, resourceName, "user-group",
882 rolesEl);
883 }
884
885 protected void importPortletPermissions(
886 LayoutCache layoutCache, long companyId, long groupId,
887 Group guestGroup, Layout layout, Element permissionsEl,
888 boolean importUserPermissions)
889 throws PortalException, SystemException {
890
891 Iterator<Element> itr = permissionsEl.elements("portlet").iterator();
892
893 while (itr.hasNext()) {
894 Element portletEl = itr.next();
895
896 String portletId = portletEl.attributeValue("portlet-id");
897
898 String resourceName = PortletConstants.getRootPortletId(portletId);
899 String resourcePrimKey = PortletPermissionUtil.getPrimaryKey(
900 layout.getPlid(), portletId);
901
902 Portlet portlet = PortletLocalServiceUtil.getPortletById(
903 companyId, resourceName);
904
905 if (portlet == null) {
906 if (_log.isDebugEnabled()) {
907 _log.debug(
908 "Do not import portlet permissions for " + portletId +
909 " because the portlet does not exist");
910 }
911 }
912 else {
913 importGroupPermissions(
914 layoutCache, companyId, groupId, resourceName,
915 resourcePrimKey, portletEl, "community-actions", true);
916
917 if (groupId != guestGroup.getGroupId()) {
918 importGroupPermissions(
919 layoutCache, companyId, guestGroup.getGroupId(),
920 resourceName, resourcePrimKey, portletEl,
921 "guest-actions", true);
922 }
923
924 if (importUserPermissions) {
925 importUserPermissions(
926 layoutCache, companyId, groupId, resourceName,
927 resourcePrimKey, portletEl, true);
928 }
929
930 importInheritedPermissions(
931 layoutCache, companyId, resourceName, resourcePrimKey,
932 portletEl, "organization", true);
933
934 importInheritedPermissions(
935 layoutCache, companyId, resourceName, resourcePrimKey,
936 portletEl, "location", true);
937
938 importInheritedPermissions(
939 layoutCache, companyId, resourceName, resourcePrimKey,
940 portletEl, "user-group", true);
941 }
942 }
943 }
944
945 protected void importPortletRoles(
946 LayoutCache layoutCache, long companyId, long groupId,
947 String portletId, Element rolesEl)
948 throws PortalException, SystemException {
949
950 String resourceName = PortletConstants.getRootPortletId(portletId);
951
952 Portlet portlet = PortletLocalServiceUtil.getPortletById(
953 companyId, resourceName);
954
955 if (portlet == null) {
956 if (_log.isDebugEnabled()) {
957 _log.debug(
958 "Do not import portlet roles for " + portletId +
959 " because the portlet does not exist");
960 }
961 }
962 else {
963 importGroupRoles(
964 layoutCache, companyId, groupId, resourceName, "community",
965 rolesEl);
966
967 importUserRoles(
968 layoutCache, companyId, groupId, resourceName, rolesEl);
969
970 importInheritedRoles(
971 layoutCache, companyId, groupId, resourceName,
972 "organization", rolesEl);
973
974 importInheritedRoles(
975 layoutCache, companyId, groupId, resourceName, "location",
976 rolesEl);
977
978 importInheritedRoles(
979 layoutCache, companyId, groupId, resourceName, "user-group",
980 rolesEl);
981 }
982 }
983
984 protected void importPortletRoles(
985 LayoutCache layoutCache, long companyId, long groupId,
986 Element rolesEl)
987 throws PortalException, SystemException {
988
989 Iterator<Element> itr = rolesEl.elements("portlet").iterator();
990
991 while (itr.hasNext()) {
992 Element portletEl = itr.next();
993
994 String portletId = portletEl.attributeValue("portlet-id");
995
996 String resourceName = PortletConstants.getRootPortletId(portletId);
997
998 Portlet portlet = PortletLocalServiceUtil.getPortletById(
999 companyId, resourceName);
1000
1001 if (portlet == null) {
1002 if (_log.isDebugEnabled()) {
1003 _log.debug(
1004 "Do not import portlet roles for " + portletId +
1005 " because the portlet does not exist");
1006 }
1007 }
1008 else {
1009 importGroupRoles(
1010 layoutCache, companyId, groupId, resourceName, "community",
1011 portletEl);
1012
1013 importUserRoles(
1014 layoutCache, companyId, groupId, resourceName, portletEl);
1015
1016 importInheritedRoles(
1017 layoutCache, companyId, groupId, resourceName,
1018 "organization", portletEl);
1019
1020 importInheritedRoles(
1021 layoutCache, companyId, groupId, resourceName, "location",
1022 portletEl);
1023
1024 importInheritedRoles(
1025 layoutCache, companyId, groupId, resourceName, "user-group",
1026 portletEl);
1027 }
1028 }
1029 }
1030
1031 protected void importRolePermissions(
1032 LayoutCache layoutCache, long companyId, String resourceName,
1033 int scope, String resourcePrimKey, Element parentEl,
1034 boolean communityRole)
1035 throws PortalException, SystemException {
1036
1037 List<Element> roleEls = parentEl.elements("role");
1038
1039 for (int i = 0; i < roleEls.size(); i++) {
1040 Element roleEl = roleEls.get(i);
1041
1042 String roleName = roleEl.attributeValue("name");
1043
1044 Role role = layoutCache.getRole(companyId, roleName);
1045
1046 if (role == null) {
1047 _log.warn(
1048 "Ignoring permissions for role with name " + roleName);
1049 }
1050 else {
1051 List<String> actions = getActions(roleEl);
1052
1053 PermissionLocalServiceUtil.setRolePermissions(
1054 role.getRoleId(), companyId, resourceName, scope,
1055 resourcePrimKey,
1056 actions.toArray(new String[actions.size()]));
1057
1058 if (communityRole) {
1059 long[] groupIds = {GetterUtil.getLong(resourcePrimKey)};
1060
1061 GroupLocalServiceUtil.addRoleGroups(
1062 role.getRoleId(), groupIds);
1063 }
1064 }
1065 }
1066 }
1067
1068 protected String importTheme(LayoutSet layoutSet, byte[] themeZip)
1069 throws IOException {
1070
1071 ThemeLoader themeLoader = ThemeLoaderFactory.getDefaultThemeLoader();
1072
1073 if (themeLoader == null) {
1074 _log.error("No theme loaders are deployed");
1075
1076 return null;
1077 }
1078
1079 ZipReader zipReader = new ZipReader(new ByteArrayInputStream(themeZip));
1080
1081 Map<String, byte[]> entries = zipReader.getEntries();
1082
1083 String lookAndFeelXML = new String(
1084 entries.get("liferay-look-and-feel.xml"));
1085
1086 String themeId = String.valueOf(layoutSet.getGroupId());
1087
1088 if (layoutSet.isPrivateLayout()) {
1089 themeId += "-private";
1090 }
1091 else {
1092 themeId += "-public";
1093 }
1094
1095 if (PropsValues.THEME_LOADER_NEW_THEME_ID_ON_IMPORT) {
1096 Date now = new Date();
1097
1098 themeId += "-" + Time.getShortTimestamp(now);
1099 }
1100
1101 String themeName = themeId;
1102
1103 lookAndFeelXML = StringUtil.replace(
1104 lookAndFeelXML,
1105 new String[] {
1106 "[$GROUP_ID$]", "[$THEME_ID$]", "[$THEME_NAME$]"
1107 },
1108 new String[] {
1109 String.valueOf(layoutSet.getGroupId()), themeId, themeName
1110 }
1111 );
1112
1113 FileUtil.deltree(themeLoader.getFileStorage() + "/" + themeId);
1114
1115 Iterator<Map.Entry<String, byte[]>> itr = entries.entrySet().iterator();
1116
1117 while (itr.hasNext()) {
1118 Map.Entry<String, byte[]> entry = itr.next();
1119
1120 String key = entry.getKey();
1121 byte[] value = entry.getValue();
1122
1123 if (key.equals("liferay-look-and-feel.xml")) {
1124 value = lookAndFeelXML.getBytes();
1125 }
1126
1127 FileUtil.write(
1128 themeLoader.getFileStorage() + "/" + themeId + "/" + key,
1129 value);
1130 }
1131
1132 themeLoader.loadThemes();
1133
1134 CommLink commLink = CommLink.getInstance();
1135
1136 MethodWrapper methodWrapper = new MethodWrapper(
1137 ThemeLoaderFactory.class.getName(), "loadThemes");
1138
1139 commLink.send(methodWrapper);
1140
1141 themeId +=
1142 PortletConstants.WAR_SEPARATOR +
1143 themeLoader.getServletContextName();
1144
1145 return PortalUtil.getJsSafePortletId(themeId);
1146 }
1147
1148 protected void importUserPermissions(
1149 LayoutCache layoutCache, long companyId, long groupId,
1150 String resourceName, String resourcePrimKey, Element parentEl,
1151 boolean portletActions)
1152 throws PortalException, SystemException {
1153
1154 Element userPermissionsEl = parentEl.element("user-permissions");
1155
1156 if (userPermissionsEl == null) {
1157 return;
1158 }
1159
1160 List<Element> userActionsEls = userPermissionsEl.elements(
1161 "user-actions");
1162
1163 for (int i = 0; i < userActionsEls.size(); i++) {
1164 Element userActionsEl = userActionsEls.get(i);
1165
1166 String emailAddress = userActionsEl.attributeValue("email-address");
1167
1168 User user = layoutCache.getUser(companyId, groupId, emailAddress);
1169
1170 if (user == null) {
1171 if (_log.isWarnEnabled()) {
1172 _log.warn(
1173 "Ignoring permissions for user with email address " +
1174 emailAddress);
1175 }
1176 }
1177 else {
1178 List<String> actions = getActions(userActionsEl);
1179
1180 Resource resource = layoutCache.getResource(
1181 companyId, groupId, resourceName,
1182 ResourceConstants.SCOPE_INDIVIDUAL, resourcePrimKey,
1183 portletActions);
1184
1185 PermissionLocalServiceUtil.setUserPermissions(
1186 user.getUserId(),
1187 actions.toArray(new String[actions.size()]),
1188 resource.getResourceId());
1189 }
1190 }
1191 }
1192
1193 protected void importUserRoles(
1194 LayoutCache layoutCache, long companyId, long groupId,
1195 String resourceName, Element parentEl)
1196 throws PortalException, SystemException {
1197
1198 Element userRolesEl = parentEl.element("user-roles");
1199
1200 if (userRolesEl == null) {
1201 return;
1202 }
1203
1204 List<Element> userEls = userRolesEl.elements("user");
1205
1206 for (int i = 0; i < userEls.size(); i++) {
1207 Element userEl = userEls.get(i);
1208
1209 String emailAddress = userEl.attributeValue("email-address");
1210
1211 User user = layoutCache.getUser(companyId, groupId, emailAddress);
1212
1213 if (user == null) {
1214 if (_log.isWarnEnabled()) {
1215 _log.warn(
1216 "Ignoring roles for user with email address " +
1217 emailAddress);
1218 }
1219 }
1220 else {
1221 importRolePermissions(
1222 layoutCache, companyId, resourceName,
1223 ResourceConstants.SCOPE_GROUP, String.valueOf(groupId),
1224 userEl, false);
1225 }
1226 }
1227 }
1228
1229 protected void mergePortlets(
1230 Layout layout, String newTypeSettings, String portletsMergeMode) {
1231
1232 try {
1233 UnicodeProperties previousProps =
1234 layout.getTypeSettingsProperties();
1235 LayoutTypePortlet previousLayoutType =
1236 (LayoutTypePortlet)layout.getLayoutType();
1237 List<String> previousColumns =
1238 previousLayoutType.getLayoutTemplate().getColumns();
1239
1240 UnicodeProperties newProps = new UnicodeProperties(true);
1241
1242 newProps.load(newTypeSettings);
1243
1244 String layoutTemplateId = newProps.getProperty(
1245 LayoutTypePortletImpl.LAYOUT_TEMPLATE_ID);
1246
1247 LayoutTemplate newLayoutTemplate =
1248 LayoutTemplateLocalServiceUtil.getLayoutTemplate(
1249 layoutTemplateId, false, null);
1250
1251 String[] lostPortletIds = new String[0];
1252
1253 for (String columnId : newLayoutTemplate.getColumns()) {
1254 String columnValue =
1255 newProps.getProperty(columnId);
1256
1257 String[] portletIds = StringUtil.split(columnValue);
1258
1259 if (!previousColumns.contains(columnId)) {
1260 lostPortletIds = ArrayUtil.append(
1261 lostPortletIds, portletIds);
1262 }
1263 else {
1264
1265 String[] previousPortletIds = StringUtil.split(
1266 previousProps.getProperty(columnId));
1267
1268 portletIds = appendPortletIds(
1269 previousPortletIds, portletIds, portletsMergeMode);
1270
1271 previousProps.setProperty(
1272 columnId, StringUtil.merge(portletIds));
1273 }
1274 }
1275
1276
1278 String columnId = previousColumns.get(0);
1279
1280 String[] portletIds = StringUtil.split(
1281 previousProps.getProperty(columnId));
1282
1283 appendPortletIds(portletIds, lostPortletIds, portletsMergeMode);
1284
1285 previousProps.setProperty(
1286 columnId, StringUtil.merge(portletIds));
1287
1288 layout.setTypeSettings(previousProps.toString());
1289
1290 }
1291 catch (IOException e) {
1292 layout.setTypeSettings(newTypeSettings);
1293 }
1294 }
1295
1296 protected String[] appendPortletIds(
1297 String[] portletIds, String[] newPortletIds,
1298 String portletsMergeMode) {
1299
1300 for (String portletId : newPortletIds) {
1301 if (ArrayUtil.contains(portletIds, portletId)) {
1302 continue;
1303 }
1304
1305 if (portletsMergeMode.equals(
1306 PortletDataHandlerKeys.PORTLETS_MERGE_MODE_ADD_TO_BOTTOM)) {
1307 portletIds = ArrayUtil.append(
1308 portletIds, portletId);
1309 }
1310 else {
1311 portletIds = ArrayUtil.append(
1312 new String[]{portletId}, portletIds);
1313 }
1314 }
1315
1316 return portletIds;
1317 }
1318
1319 private static Log _log = LogFactory.getLog(LayoutImporter.class);
1320
1321 private PortletImporter _portletImporter = new PortletImporter();
1322
1323}