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