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