001
014
015 package com.liferay.portal.lar;
016
017 import com.liferay.counter.service.CounterLocalServiceUtil;
018 import com.liferay.portal.LARFileException;
019 import com.liferay.portal.LARTypeException;
020 import com.liferay.portal.LayoutImportException;
021 import com.liferay.portal.LayoutPrototypeException;
022 import com.liferay.portal.LocaleException;
023 import com.liferay.portal.NoSuchLayoutException;
024 import com.liferay.portal.NoSuchLayoutPrototypeException;
025 import com.liferay.portal.NoSuchLayoutSetPrototypeException;
026 import com.liferay.portal.kernel.cluster.ClusterExecutorUtil;
027 import com.liferay.portal.kernel.cluster.ClusterRequest;
028 import com.liferay.portal.kernel.exception.PortalException;
029 import com.liferay.portal.kernel.exception.SystemException;
030 import com.liferay.portal.kernel.language.LanguageUtil;
031 import com.liferay.portal.kernel.lar.ExportImportThreadLocal;
032 import com.liferay.portal.kernel.lar.PortletDataContext;
033 import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
034 import com.liferay.portal.kernel.lar.StagedModelDataHandlerUtil;
035 import com.liferay.portal.kernel.lar.UserIdStrategy;
036 import com.liferay.portal.kernel.log.Log;
037 import com.liferay.portal.kernel.log.LogFactoryUtil;
038 import com.liferay.portal.kernel.search.Indexer;
039 import com.liferay.portal.kernel.search.IndexerRegistryUtil;
040 import com.liferay.portal.kernel.staging.StagingUtil;
041 import com.liferay.portal.kernel.util.ArrayUtil;
042 import com.liferay.portal.kernel.util.CharPool;
043 import com.liferay.portal.kernel.util.FileUtil;
044 import com.liferay.portal.kernel.util.GetterUtil;
045 import com.liferay.portal.kernel.util.LocaleUtil;
046 import com.liferay.portal.kernel.util.MapUtil;
047 import com.liferay.portal.kernel.util.MethodHandler;
048 import com.liferay.portal.kernel.util.MethodKey;
049 import com.liferay.portal.kernel.util.ReleaseInfo;
050 import com.liferay.portal.kernel.util.StringBundler;
051 import com.liferay.portal.kernel.util.StringPool;
052 import com.liferay.portal.kernel.util.StringUtil;
053 import com.liferay.portal.kernel.util.Time;
054 import com.liferay.portal.kernel.util.Tuple;
055 import com.liferay.portal.kernel.util.UnicodeProperties;
056 import com.liferay.portal.kernel.util.Validator;
057 import com.liferay.portal.kernel.xml.Attribute;
058 import com.liferay.portal.kernel.xml.Document;
059 import com.liferay.portal.kernel.xml.Element;
060 import com.liferay.portal.kernel.xml.Node;
061 import com.liferay.portal.kernel.xml.SAXReaderUtil;
062 import com.liferay.portal.kernel.zip.ZipReader;
063 import com.liferay.portal.kernel.zip.ZipReaderFactoryUtil;
064 import com.liferay.portal.model.Group;
065 import com.liferay.portal.model.Layout;
066 import com.liferay.portal.model.LayoutConstants;
067 import com.liferay.portal.model.LayoutPrototype;
068 import com.liferay.portal.model.LayoutSet;
069 import com.liferay.portal.model.LayoutSetPrototype;
070 import com.liferay.portal.model.LayoutTemplate;
071 import com.liferay.portal.model.LayoutTypePortlet;
072 import com.liferay.portal.model.LayoutTypePortletConstants;
073 import com.liferay.portal.model.Portlet;
074 import com.liferay.portal.model.PortletConstants;
075 import com.liferay.portal.model.ResourceConstants;
076 import com.liferay.portal.model.Role;
077 import com.liferay.portal.model.RoleConstants;
078 import com.liferay.portal.model.User;
079 import com.liferay.portal.model.impl.ColorSchemeImpl;
080 import com.liferay.portal.security.permission.ActionKeys;
081 import com.liferay.portal.security.permission.PermissionCacheUtil;
082 import com.liferay.portal.service.GroupLocalServiceUtil;
083 import com.liferay.portal.service.ImageLocalServiceUtil;
084 import com.liferay.portal.service.LayoutLocalServiceUtil;
085 import com.liferay.portal.service.LayoutPrototypeLocalServiceUtil;
086 import com.liferay.portal.service.LayoutSetLocalServiceUtil;
087 import com.liferay.portal.service.LayoutSetPrototypeLocalServiceUtil;
088 import com.liferay.portal.service.LayoutTemplateLocalServiceUtil;
089 import com.liferay.portal.service.PortletLocalServiceUtil;
090 import com.liferay.portal.service.ResourceLocalServiceUtil;
091 import com.liferay.portal.service.ResourcePermissionLocalServiceUtil;
092 import com.liferay.portal.service.RoleLocalServiceUtil;
093 import com.liferay.portal.service.ServiceContext;
094 import com.liferay.portal.service.ServiceContextThreadLocal;
095 import com.liferay.portal.service.persistence.LayoutUtil;
096 import com.liferay.portal.service.persistence.UserUtil;
097 import com.liferay.portal.servlet.filters.cache.CacheUtil;
098 import com.liferay.portal.theme.ThemeLoader;
099 import com.liferay.portal.theme.ThemeLoaderFactory;
100 import com.liferay.portal.util.PortalUtil;
101 import com.liferay.portal.util.PortletKeys;
102 import com.liferay.portal.util.PropsValues;
103 import com.liferay.portlet.journal.lar.JournalPortletDataHandler;
104 import com.liferay.portlet.journal.model.JournalArticle;
105 import com.liferay.portlet.journal.service.JournalContentSearchLocalServiceUtil;
106 import com.liferay.portlet.journalcontent.util.JournalContentUtil;
107 import com.liferay.portlet.sites.util.SitesUtil;
108
109 import java.io.File;
110 import java.io.IOException;
111 import java.io.InputStream;
112
113 import java.util.ArrayList;
114 import java.util.Date;
115 import java.util.HashSet;
116 import java.util.List;
117 import java.util.Locale;
118 import java.util.Map;
119 import java.util.Set;
120
121 import org.apache.commons.lang.time.StopWatch;
122
123
136 public class LayoutImporter {
137
138 public void importLayouts(
139 long userId, long groupId, boolean privateLayout,
140 Map<String, String[]> parameterMap, File file)
141 throws Exception {
142
143 try {
144 ExportImportThreadLocal.setLayoutImportInProcess(true);
145
146 doImportLayouts(userId, groupId, privateLayout, parameterMap, file);
147 }
148 finally {
149 ExportImportThreadLocal.setLayoutImportInProcess(false);
150
151 CacheUtil.clearCache();
152 JournalContentUtil.clearCache();
153 PermissionCacheUtil.clearCache();
154 }
155 }
156
157 protected String[] appendPortletIds(
158 String[] portletIds, String[] newPortletIds, String portletsMergeMode) {
159
160 for (String portletId : newPortletIds) {
161 if (ArrayUtil.contains(portletIds, portletId)) {
162 continue;
163 }
164
165 if (portletsMergeMode.equals(
166 PortletDataHandlerKeys.PORTLETS_MERGE_MODE_ADD_TO_BOTTOM)) {
167
168 portletIds = ArrayUtil.append(portletIds, portletId);
169 }
170 else {
171 portletIds = ArrayUtil.append(
172 new String[] {portletId}, portletIds);
173 }
174 }
175
176 return portletIds;
177 }
178
179 protected void deleteMissingLayouts(
180 long groupId, boolean privateLayout, List<Layout> newLayouts,
181 List<Layout> previousLayouts, ServiceContext serviceContext)
182 throws Exception {
183
184
185
186 Set<String> existingLayoutUuids = new HashSet<String>();
187
188 Group group = GroupLocalServiceUtil.getGroup(groupId);
189
190 if (group.hasStagingGroup()) {
191 Group stagingGroup = group.getStagingGroup();
192
193 if (stagingGroup.hasPrivateLayouts() ||
194 stagingGroup.hasPublicLayouts()) {
195
196 List<Layout> layouts = LayoutLocalServiceUtil.getLayouts(
197 stagingGroup.getGroupId(), privateLayout);
198
199 for (Layout layout : layouts) {
200 existingLayoutUuids.add(layout.getUuid());
201 }
202 }
203 }
204 else {
205 for (Layout layout : newLayouts) {
206 existingLayoutUuids.add(layout.getUuid());
207 }
208 }
209
210 if (_log.isDebugEnabled() && !existingLayoutUuids.isEmpty()) {
211 _log.debug("Delete missing layouts");
212 }
213
214 for (Layout layout : previousLayouts) {
215 if (!existingLayoutUuids.contains(layout.getUuid())) {
216 try {
217 LayoutLocalServiceUtil.deleteLayout(
218 layout, privateLayout, serviceContext);
219 }
220 catch (NoSuchLayoutException nsle) {
221 }
222 }
223 }
224 }
225
226 protected void doImportLayouts(
227 long userId, long groupId, boolean privateLayout,
228 Map<String, String[]> parameterMap, File file)
229 throws Exception {
230
231 boolean deleteMissingLayouts = MapUtil.getBoolean(
232 parameterMap, PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
233 Boolean.TRUE.booleanValue());
234 boolean deletePortletData = MapUtil.getBoolean(
235 parameterMap, PortletDataHandlerKeys.DELETE_PORTLET_DATA);
236 boolean importCategories = MapUtil.getBoolean(
237 parameterMap, PortletDataHandlerKeys.CATEGORIES);
238 boolean importPermissions = MapUtil.getBoolean(
239 parameterMap, PortletDataHandlerKeys.PERMISSIONS);
240 boolean importPublicLayoutPermissions = MapUtil.getBoolean(
241 parameterMap, PortletDataHandlerKeys.PUBLIC_LAYOUT_PERMISSIONS);
242 boolean importPortletData = MapUtil.getBoolean(
243 parameterMap, PortletDataHandlerKeys.PORTLET_DATA);
244 boolean importPortletSetup = MapUtil.getBoolean(
245 parameterMap, PortletDataHandlerKeys.PORTLET_SETUP);
246 boolean importPortletArchivedSetups = MapUtil.getBoolean(
247 parameterMap, PortletDataHandlerKeys.PORTLET_ARCHIVED_SETUPS);
248 boolean importPortletUserPreferences = MapUtil.getBoolean(
249 parameterMap, PortletDataHandlerKeys.PORTLET_USER_PREFERENCES);
250 boolean importTheme = MapUtil.getBoolean(
251 parameterMap, PortletDataHandlerKeys.THEME);
252 boolean importThemeSettings = MapUtil.getBoolean(
253 parameterMap, PortletDataHandlerKeys.THEME_REFERENCE);
254 boolean importLogo = MapUtil.getBoolean(
255 parameterMap, PortletDataHandlerKeys.LOGO);
256 boolean importLayoutSetSettings = MapUtil.getBoolean(
257 parameterMap, PortletDataHandlerKeys.LAYOUT_SET_SETTINGS);
258
259 boolean layoutSetPrototypeLinkEnabled = MapUtil.getBoolean(
260 parameterMap,
261 PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_LINK_ENABLED, true);
262
263 Group group = GroupLocalServiceUtil.getGroup(groupId);
264
265 if (group.isLayoutSetPrototype()) {
266 layoutSetPrototypeLinkEnabled = false;
267 }
268
269
270
271 String layoutsImportMode = MapUtil.getString(
272 parameterMap, PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE,
273 PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_MERGE_BY_LAYOUT_UUID);
274 String portletsMergeMode = MapUtil.getString(
275 parameterMap, PortletDataHandlerKeys.PORTLETS_MERGE_MODE,
276 PortletDataHandlerKeys.PORTLETS_MERGE_MODE_REPLACE);
277 String userIdStrategy = MapUtil.getString(
278 parameterMap, PortletDataHandlerKeys.USER_ID_STRATEGY);
279
280 if (_log.isDebugEnabled()) {
281 _log.debug("Delete portlet data " + deletePortletData);
282 _log.debug("Import categories " + importCategories);
283 _log.debug("Import permissions " + importPermissions);
284 _log.debug("Import portlet data " + importPortletData);
285 _log.debug("Import portlet setup " + importPortletSetup);
286 _log.debug(
287 "Import portlet archived setups " +
288 importPortletArchivedSetups);
289 _log.debug(
290 "Import portlet user preferences " +
291 importPortletUserPreferences);
292 _log.debug("Import theme " + importTheme);
293 }
294
295 StopWatch stopWatch = null;
296
297 if (_log.isInfoEnabled()) {
298 stopWatch = new StopWatch();
299
300 stopWatch.start();
301 }
302
303 LayoutCache layoutCache = new LayoutCache();
304
305 LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
306 groupId, privateLayout);
307
308 long companyId = layoutSet.getCompanyId();
309
310 User user = UserUtil.findByPrimaryKey(userId);
311
312 UserIdStrategy strategy = _portletImporter.getUserIdStrategy(
313 user, userIdStrategy);
314
315 ZipReader zipReader = ZipReaderFactoryUtil.getZipReader(file);
316
317 PortletDataContext portletDataContext = new PortletDataContextImpl(
318 companyId, groupId, parameterMap, new HashSet<String>(), strategy,
319 zipReader);
320
321 portletDataContext.setPortetDataContextListener(
322 new PortletDataContextListenerImpl(portletDataContext));
323
324 portletDataContext.setPrivateLayout(privateLayout);
325
326
327
328 Element rootElement = null;
329 InputStream themeZip = null;
330
331
332
333 String xml = portletDataContext.getZipEntryAsString("/manifest.xml");
334
335 if (xml == null) {
336 throw new LARFileException("manifest.xml not found in the LAR");
337 }
338
339 try {
340 Document document = SAXReaderUtil.read(xml);
341
342 rootElement = document.getRootElement();
343 }
344 catch (Exception e) {
345 throw new LARFileException(e);
346 }
347
348
349
350 Element headerElement = rootElement.element("header");
351
352 int buildNumber = ReleaseInfo.getBuildNumber();
353
354 int importBuildNumber = GetterUtil.getInteger(
355 headerElement.attributeValue("build-number"));
356
357 if (buildNumber != importBuildNumber) {
358 throw new LayoutImportException(
359 "LAR build number " + importBuildNumber + " does not match " +
360 "portal build number " + buildNumber);
361 }
362
363
364
365 String larType = headerElement.attributeValue("type");
366
367 if (!larType.equals("layout-prototype") &&
368 !larType.equals("layout-set") &&
369 !larType.equals("layout-set-prototype")) {
370
371 throw new LARTypeException(
372 "Invalid type of LAR file (" + larType + ")");
373 }
374
375
376
377 Locale[] sourceAvailableLocales = LocaleUtil.fromLanguageIds(
378 StringUtil.split(
379 headerElement.attributeValue("available-locales")));
380
381 Locale[] targetAvailableLocales = LanguageUtil.getAvailableLocales();
382
383 for (Locale sourceAvailableLocale : sourceAvailableLocales) {
384 if (!ArrayUtil.contains(
385 targetAvailableLocales, sourceAvailableLocale)) {
386
387 LocaleException le = new LocaleException();
388
389 le.setSourceAvailableLocales(sourceAvailableLocales);
390 le.setTargetAvailableLocales(targetAvailableLocales);
391
392 throw le;
393 }
394 }
395
396
397
398 Element layoutsElement = rootElement.element("layouts");
399
400 List<Element> layoutElements = layoutsElement.elements("layout");
401
402 validateLayoutPrototypes(companyId, layoutsElement, layoutElements);
403
404
405
406 long sourceGroupId = GetterUtil.getLong(
407 headerElement.attributeValue("group-id"));
408
409 portletDataContext.setSourceGroupId(sourceGroupId);
410
411
412
413 String layoutSetPrototypeUuid = layoutsElement.attributeValue(
414 "layout-set-prototype-uuid");
415
416 if (group.isLayoutPrototype() && larType.equals("layout-prototype")) {
417 deleteMissingLayouts = false;
418
419 LayoutPrototype layoutPrototype =
420 LayoutPrototypeLocalServiceUtil.getLayoutPrototype(
421 group.getClassPK());
422
423 String layoutPrototypeUuid = GetterUtil.getString(
424 headerElement.attributeValue("type-uuid"));
425
426 LayoutPrototype existingLayoutPrototype = null;
427
428 if (Validator.isNotNull(layoutPrototypeUuid)) {
429 try {
430 existingLayoutPrototype =
431 LayoutPrototypeLocalServiceUtil.
432 getLayoutPrototypeByUuidAndCompanyId(
433 layoutPrototypeUuid, companyId);
434 }
435 catch (NoSuchLayoutPrototypeException nslpe) {
436 }
437 }
438
439 if (existingLayoutPrototype == null) {
440 layoutPrototype.setUuid(layoutPrototypeUuid);
441
442 LayoutPrototypeLocalServiceUtil.updateLayoutPrototype(
443 layoutPrototype);
444 }
445 }
446 else if (group.isLayoutSetPrototype() &&
447 larType.equals("layout-set-prototype")) {
448
449 LayoutSetPrototype layoutSetPrototype =
450 LayoutSetPrototypeLocalServiceUtil.getLayoutSetPrototype(
451 group.getClassPK());
452
453 String importedLayoutSetPrototypeUuid = GetterUtil.getString(
454 headerElement.attributeValue("type-uuid"));
455
456 LayoutSetPrototype existingLayoutSetPrototype = null;
457
458 if (Validator.isNotNull(importedLayoutSetPrototypeUuid)) {
459 try {
460 existingLayoutSetPrototype =
461 LayoutSetPrototypeLocalServiceUtil.
462 getLayoutSetPrototypeByUuidAndCompanyId(
463 importedLayoutSetPrototypeUuid, companyId);
464 }
465 catch (NoSuchLayoutSetPrototypeException nslspe) {
466 }
467 }
468
469 if (existingLayoutSetPrototype == null) {
470 layoutSetPrototype.setUuid(importedLayoutSetPrototypeUuid);
471
472 LayoutSetPrototypeLocalServiceUtil.updateLayoutSetPrototype(
473 layoutSetPrototype);
474 }
475 }
476 else if (larType.equals("layout-set-prototype")) {
477 layoutSetPrototypeUuid = GetterUtil.getString(
478 headerElement.attributeValue("type-uuid"));
479 }
480
481 ServiceContext serviceContext =
482 ServiceContextThreadLocal.getServiceContext();
483
484 if (Validator.isNotNull(layoutSetPrototypeUuid)) {
485 layoutSet.setLayoutSetPrototypeUuid(layoutSetPrototypeUuid);
486 layoutSet.setLayoutSetPrototypeLinkEnabled(
487 layoutSetPrototypeLinkEnabled);
488
489 LayoutSetLocalServiceUtil.updateLayoutSet(layoutSet);
490 }
491
492
493
494 if (importTheme) {
495 themeZip = portletDataContext.getZipEntryAsInputStream("theme.zip");
496 }
497
498
499
500 String themeId = layoutSet.getThemeId();
501 String colorSchemeId = layoutSet.getColorSchemeId();
502
503 if (importThemeSettings) {
504 Attribute themeIdAttribute = headerElement.attribute("theme-id");
505
506 if (themeIdAttribute != null) {
507 themeId = themeIdAttribute.getValue();
508 }
509
510 Attribute colorSchemeIdAttribute = headerElement.attribute(
511 "color-scheme-id");
512
513 if (colorSchemeIdAttribute != null) {
514 colorSchemeId = colorSchemeIdAttribute.getValue();
515 }
516 }
517
518 if (importLogo) {
519 String logoPath = headerElement.attributeValue("logo-path");
520
521 byte[] iconBytes = portletDataContext.getZipEntryAsByteArray(
522 logoPath);
523
524 if ((iconBytes != null) && (iconBytes.length > 0)) {
525 File logo = FileUtil.createTempFile(iconBytes);
526
527 LayoutSetLocalServiceUtil.updateLogo(
528 groupId, privateLayout, true, logo);
529 }
530 else {
531 LayoutSetLocalServiceUtil.updateLogo(
532 groupId, privateLayout, false, (File)null);
533 }
534 }
535
536 if (importLayoutSetSettings) {
537 String settings = GetterUtil.getString(
538 headerElement.elementText("settings"));
539
540 LayoutSetLocalServiceUtil.updateSettings(
541 groupId, privateLayout, settings);
542 }
543
544 String css = GetterUtil.getString(headerElement.elementText("css"));
545
546 if (themeZip != null) {
547 String importThemeId = importTheme(layoutSet, themeZip);
548
549 if (importThemeId != null) {
550 themeId = importThemeId;
551 colorSchemeId =
552 ColorSchemeImpl.getDefaultRegularColorSchemeId();
553 }
554
555 if (_log.isDebugEnabled()) {
556 _log.debug(
557 "Importing theme takes " + stopWatch.getTime() + " ms");
558 }
559 }
560
561 boolean wapTheme = false;
562
563 LayoutSetLocalServiceUtil.updateLookAndFeel(
564 groupId, privateLayout, themeId, colorSchemeId, css, wapTheme);
565
566
567
568
569
570 if (importPermissions) {
571 _permissionImporter.readPortletDataPermissions(portletDataContext);
572 }
573
574 if (importCategories || group.isCompany()) {
575 _portletImporter.readAssetCategories(portletDataContext);
576 }
577
578 _portletImporter.readAssetTags(portletDataContext);
579 _portletImporter.readComments(portletDataContext);
580 _portletImporter.readExpandoTables(portletDataContext);
581 _portletImporter.readLocks(portletDataContext);
582 _portletImporter.readRatingsEntries(portletDataContext);
583
584
585
586 List<Layout> previousLayouts = LayoutUtil.findByG_P(
587 groupId, privateLayout);
588
589
590
591 if (Validator.isNotNull(layoutSetPrototypeUuid) &&
592 layoutSetPrototypeLinkEnabled) {
593
594 LayoutSetPrototype layoutSetPrototype =
595 LayoutSetPrototypeLocalServiceUtil.
596 getLayoutSetPrototypeByUuidAndCompanyId(
597 layoutSetPrototypeUuid, companyId);
598
599 Group layoutSetPrototypeGroup = layoutSetPrototype.getGroup();
600
601 for (Layout layout : previousLayouts) {
602 String sourcePrototypeLayoutUuid =
603 layout.getSourcePrototypeLayoutUuid();
604
605 if (Validator.isNull(layout.getSourcePrototypeLayoutUuid())) {
606 continue;
607 }
608
609 Layout sourcePrototypeLayout = LayoutUtil.fetchByUUID_G_P(
610 sourcePrototypeLayoutUuid,
611 layoutSetPrototypeGroup.getGroupId(), true);
612
613 if (sourcePrototypeLayout == null) {
614 LayoutLocalServiceUtil.deleteLayout(
615 layout, false, serviceContext);
616 }
617 }
618 }
619
620 List<Layout> newLayouts = new ArrayList<Layout>();
621
622 Map<Long, Layout> newLayoutsMap =
623 (Map<Long, Layout>)portletDataContext.getNewPrimaryKeysMap(
624 Layout.class);
625
626 if (_log.isDebugEnabled()) {
627 if (layoutElements.size() > 0) {
628 _log.debug("Importing layouts");
629 }
630 }
631
632 for (Element layoutElement : layoutElements) {
633 importLayout(
634 portletDataContext, user, layoutCache, previousLayouts,
635 newLayouts, newLayoutsMap, portletsMergeMode, themeId,
636 colorSchemeId, layoutsImportMode, privateLayout,
637 importPermissions, importPublicLayoutPermissions,
638 importThemeSettings, rootElement, layoutElement);
639 }
640
641 Element portletsElement = rootElement.element("portlets");
642
643 List<Element> portletElements = portletsElement.elements("portlet");
644
645
646
647 if (deletePortletData) {
648 if (_log.isDebugEnabled()) {
649 if (portletElements.size() > 0) {
650 _log.debug("Deleting portlet data");
651 }
652 }
653
654 for (Element portletElement : portletElements) {
655 String portletId = portletElement.attributeValue("portlet-id");
656 long layoutId = GetterUtil.getLong(
657 portletElement.attributeValue("layout-id"));
658 long plid = newLayoutsMap.get(layoutId).getPlid();
659
660 portletDataContext.setPlid(plid);
661
662 _portletImporter.deletePortletData(
663 portletDataContext, portletId, plid);
664 }
665 }
666
667
668
669 if (_log.isDebugEnabled()) {
670 if (portletElements.size() > 0) {
671 _log.debug("Importing portlets");
672 }
673 }
674
675 for (Element portletElement : portletElements) {
676 String portletPath = portletElement.attributeValue("path");
677 String portletId = portletElement.attributeValue("portlet-id");
678 long layoutId = GetterUtil.getLong(
679 portletElement.attributeValue("layout-id"));
680 long oldPlid = GetterUtil.getLong(
681 portletElement.attributeValue("old-plid"));
682
683 Portlet portlet = PortletLocalServiceUtil.getPortletById(
684 portletDataContext.getCompanyId(), portletId);
685
686 if (!portlet.isActive() || portlet.isUndeployedPortlet()) {
687 continue;
688 }
689
690 Layout layout = newLayoutsMap.get(layoutId);
691
692 long plid = LayoutConstants.DEFAULT_PLID;
693
694 if (layout != null) {
695 plid = layout.getPlid();
696 }
697
698 layout = LayoutUtil.fetchByPrimaryKey(plid);
699
700 if ((layout == null) && !group.isCompany()) {
701 continue;
702 }
703
704 portletDataContext.setPlid(plid);
705 portletDataContext.setOldPlid(oldPlid);
706
707 Document portletDocument = SAXReaderUtil.read(
708 portletDataContext.getZipEntryAsString(portletPath));
709
710 portletElement = portletDocument.getRootElement();
711
712
713
714
715
716
717 _portletImporter.setPortletScope(
718 portletDataContext, portletElement);
719
720 long portletPreferencesGroupId = groupId;
721
722 Element portletDataElement = portletElement.element("portlet-data");
723
724 boolean importData =
725 importPortletData && (portletDataElement != null);
726
727 try {
728 if ((layout != null) && !group.isCompany()) {
729 portletPreferencesGroupId = layout.getGroupId();
730 }
731
732
733
734 _portletImporter.importPortletPreferences(
735 portletDataContext, layoutSet.getCompanyId(),
736 portletPreferencesGroupId, layout, null, portletElement,
737 importPortletSetup, importPortletArchivedSetups,
738 importPortletUserPreferences, false, importData);
739
740
741
742 if (importData) {
743 _portletImporter.importPortletData(
744 portletDataContext, portletId, plid,
745 portletDataElement);
746 }
747 }
748 finally {
749 _portletImporter.resetPortletScope(
750 portletDataContext, portletPreferencesGroupId);
751 }
752
753
754
755 if (importPermissions) {
756 _permissionImporter.importPortletPermissions(
757 layoutCache, companyId, groupId, userId, layout,
758 portletElement, portletId);
759 }
760
761
762
763 _portletImporter.importPortletPreferences(
764 portletDataContext, layoutSet.getCompanyId(), groupId, null,
765 null, portletElement, importPortletSetup,
766 importPortletArchivedSetups, importPortletUserPreferences,
767 false, importData);
768 }
769
770 if (importPermissions) {
771 if (userId > 0) {
772 Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
773 User.class);
774
775 indexer.reindex(userId);
776 }
777 }
778
779
780
781 _portletImporter.readAssetLinks(portletDataContext);
782
783
784
785 if (deleteMissingLayouts) {
786 deleteMissingLayouts(
787 groupId, privateLayout, newLayouts, previousLayouts,
788 serviceContext);
789 }
790
791
792
793 layoutSet = LayoutSetLocalServiceUtil.updatePageCount(
794 groupId, privateLayout);
795
796 if (_log.isInfoEnabled()) {
797 _log.info("Importing layouts takes " + stopWatch.getTime() + " ms");
798 }
799
800
801
802 GroupLocalServiceUtil.updateSite(groupId, true);
803
804
805
806
807 long lastMergeTime = System.currentTimeMillis();
808
809 for (Layout layout : newLayouts) {
810 boolean modifiedTypeSettingsProperties = false;
811
812 UnicodeProperties typeSettingsProperties =
813 layout.getTypeSettingsProperties();
814
815
816
817 String articleId = typeSettingsProperties.getProperty("article-id");
818
819 if (Validator.isNotNull(articleId)) {
820 Map<String, String> articleIds =
821 (Map<String, String>)portletDataContext.
822 getNewPrimaryKeysMap(
823 JournalArticle.class + ".articleId");
824
825 typeSettingsProperties.setProperty(
826 "article-id",
827 MapUtil.getString(articleIds, articleId, articleId));
828
829 modifiedTypeSettingsProperties = true;
830 }
831
832
833
834 if (layoutsImportMode.equals(
835 PortletDataHandlerKeys.
836 LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE)) {
837
838 typeSettingsProperties.setProperty(
839 SitesUtil.LAST_MERGE_TIME, String.valueOf(lastMergeTime));
840
841 modifiedTypeSettingsProperties = true;
842 }
843
844 if (modifiedTypeSettingsProperties) {
845 LayoutUtil.update(layout);
846 }
847 }
848
849
850
851 if (layoutsImportMode.equals(
852 PortletDataHandlerKeys.
853 LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE)) {
854
855 UnicodeProperties settingsProperties =
856 layoutSet.getSettingsProperties();
857
858 settingsProperties.setProperty(
859 SitesUtil.LAST_MERGE_TIME, String.valueOf(lastMergeTime));
860
861 LayoutSetLocalServiceUtil.updateLayoutSet(layoutSet);
862 }
863
864 zipReader.close();
865 }
866
867 protected void fixTypeSettings(Layout layout) throws Exception {
868 if (!layout.isTypeURL()) {
869 return;
870 }
871
872 UnicodeProperties typeSettings = layout.getTypeSettingsProperties();
873
874 String url = GetterUtil.getString(typeSettings.getProperty("url"));
875
876 String friendlyURLPrivateGroupPath =
877 PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_GROUP_SERVLET_MAPPING;
878 String friendlyURLPrivateUserPath =
879 PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING;
880 String friendlyURLPublicPath =
881 PropsValues.LAYOUT_FRIENDLY_URL_PUBLIC_SERVLET_MAPPING;
882
883 if (!url.startsWith(friendlyURLPrivateGroupPath) &&
884 !url.startsWith(friendlyURLPrivateUserPath) &&
885 !url.startsWith(friendlyURLPublicPath)) {
886
887 return;
888 }
889
890 int x = url.indexOf(CharPool.SLASH, 1);
891
892 if (x == -1) {
893 return;
894 }
895
896 int y = url.indexOf(CharPool.SLASH, x + 1);
897
898 if (y == -1) {
899 return;
900 }
901
902 String friendlyURL = url.substring(x, y);
903
904 if (!friendlyURL.equals(LayoutExporter.SAME_GROUP_FRIENDLY_URL)) {
905 return;
906 }
907
908 Group group = layout.getGroup();
909
910 typeSettings.setProperty(
911 "url",
912 url.substring(0, x) + group.getFriendlyURL() + url.substring(y));
913 }
914
915 protected String getLayoutSetPrototype(
916 PortletDataContext portletDataContext, String layoutSetPrototypeUuid) {
917
918 StringBundler sb = new StringBundler(3);
919
920 sb.append(portletDataContext.getSourceRootPath());
921 sb.append("/layout-set-prototype/");
922 sb.append(layoutSetPrototypeUuid);
923
924 return sb.toString();
925 }
926
927 protected void importJournalArticle(
928 PortletDataContext portletDataContext, Layout layout,
929 Element layoutElement)
930 throws Exception {
931
932 UnicodeProperties typeSettingsProperties =
933 layout.getTypeSettingsProperties();
934
935 String articleId = typeSettingsProperties.getProperty(
936 "article-id", StringPool.BLANK);
937
938 if (Validator.isNull(articleId)) {
939 return;
940 }
941
942 JournalPortletDataHandler.importReferencedData(
943 portletDataContext, layoutElement);
944
945 Element structureElement = layoutElement.element("structure");
946
947 if (structureElement != null) {
948 StagedModelDataHandlerUtil.importStagedModel(
949 portletDataContext, structureElement);
950 }
951
952 Element templateElement = layoutElement.element("template");
953
954 if (templateElement != null) {
955 StagedModelDataHandlerUtil.importStagedModel(
956 portletDataContext, templateElement);
957 }
958
959 Element articleElement = layoutElement.element("article");
960
961 if (articleElement != null) {
962 JournalPortletDataHandler.importArticle(
963 portletDataContext, articleElement);
964 }
965
966 Map<String, String> articleIds =
967 (Map<String, String>)portletDataContext.getNewPrimaryKeysMap(
968 JournalArticle.class + ".articleId");
969
970 articleId = MapUtil.getString(articleIds, articleId, articleId);
971
972 typeSettingsProperties.setProperty("article-id", articleId);
973
974 JournalContentSearchLocalServiceUtil.updateContentSearch(
975 portletDataContext.getScopeGroupId(), layout.isPrivateLayout(),
976 layout.getLayoutId(), StringPool.BLANK, articleId, true);
977 }
978
979 protected void importLayout(
980 PortletDataContext portletDataContext, User user,
981 LayoutCache layoutCache, List<Layout> previousLayouts,
982 List<Layout> newLayouts, Map<Long, Layout> newLayoutsMap,
983 String portletsMergeMode, String themeId, String colorSchemeId,
984 String layoutsImportMode, boolean privateLayout,
985 boolean importPermissions, boolean importPublicLayoutPermissions,
986 boolean importThemeSettings, Element rootElement,
987 Element layoutElement)
988 throws Exception {
989
990 long groupId = portletDataContext.getGroupId();
991
992 String layoutUuid = GetterUtil.getString(
993 layoutElement.attributeValue("layout-uuid"));
994
995 long layoutId = GetterUtil.getInteger(
996 layoutElement.attributeValue("layout-id"));
997
998 long oldLayoutId = layoutId;
999
1000 boolean deleteLayout = GetterUtil.getBoolean(
1001 layoutElement.attributeValue("delete"));
1002
1003 if (deleteLayout) {
1004 Layout layout = LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
1005 layoutUuid, groupId, privateLayout);
1006
1007 if (layout != null) {
1008 newLayoutsMap.put(oldLayoutId, layout);
1009
1010 ServiceContext serviceContext =
1011 ServiceContextThreadLocal.getServiceContext();
1012
1013 LayoutLocalServiceUtil.deleteLayout(
1014 layout, false, serviceContext);
1015 }
1016
1017 return;
1018 }
1019
1020 String path = layoutElement.attributeValue("path");
1021
1022 if (!portletDataContext.isPathNotProcessed(path)) {
1023 return;
1024 }
1025
1026 Layout layout = (Layout)portletDataContext.getZipEntryAsObject(path);
1027
1028 Layout existingLayout = null;
1029 Layout importedLayout = null;
1030
1031 String friendlyURL = layout.getFriendlyURL();
1032
1033 if (layoutsImportMode.equals(
1034 PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_ADD_AS_NEW)) {
1035
1036 layoutId = LayoutLocalServiceUtil.getNextLayoutId(
1037 groupId, privateLayout);
1038 friendlyURL = StringPool.SLASH + layoutId;
1039 }
1040 else if (layoutsImportMode.equals(
1041 PortletDataHandlerKeys.
1042 LAYOUTS_IMPORT_MODE_MERGE_BY_LAYOUT_NAME)) {
1043
1044 Locale locale = LocaleUtil.getDefault();
1045
1046 String localizedName = layout.getName(locale);
1047
1048 for (Layout curLayout : previousLayouts) {
1049 if (localizedName.equals(curLayout.getName(locale)) ||
1050 friendlyURL.equals(curLayout.getFriendlyURL())) {
1051
1052 existingLayout = curLayout;
1053
1054 break;
1055 }
1056 }
1057
1058 if (existingLayout == null) {
1059 layoutId = LayoutLocalServiceUtil.getNextLayoutId(
1060 groupId, privateLayout);
1061 }
1062 }
1063 else if (layoutsImportMode.equals(
1064 PortletDataHandlerKeys.
1065 LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE)) {
1066
1067 existingLayout = LayoutUtil.fetchByG_P_SPLU(
1068 groupId, privateLayout, layout.getUuid());
1069
1070 if (SitesUtil.isLayoutModifiedSinceLastMerge(existingLayout)) {
1071 newLayoutsMap.put(oldLayoutId, existingLayout);
1072
1073 return;
1074 }
1075 }
1076 else {
1077
1078
1079
1080
1081 existingLayout = LayoutUtil.fetchByUUID_G_P(
1082 layout.getUuid(), groupId, privateLayout);
1083
1084 if (existingLayout == null) {
1085 existingLayout = LayoutUtil.fetchByG_P_F(
1086 groupId, privateLayout, friendlyURL);
1087 }
1088
1089 if (existingLayout == null) {
1090 layoutId = LayoutLocalServiceUtil.getNextLayoutId(
1091 groupId, privateLayout);
1092 }
1093 }
1094
1095 if (_log.isDebugEnabled()) {
1096 if (existingLayout == null) {
1097 _log.debug(
1098 "Layout with {groupId=" + groupId + ",privateLayout=" +
1099 privateLayout + ",layoutId=" + layoutId +
1100 "} does not exist");
1101 }
1102 else {
1103 _log.debug(
1104 "Layout with {groupId=" + groupId + ",privateLayout=" +
1105 privateLayout + ",layoutId=" + layoutId + "} exists");
1106 }
1107 }
1108
1109 if (existingLayout == null) {
1110 long plid = CounterLocalServiceUtil.increment();
1111
1112 importedLayout = LayoutUtil.create(plid);
1113
1114 if (layoutsImportMode.equals(
1115 PortletDataHandlerKeys.
1116 LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE)) {
1117
1118 importedLayout.setSourcePrototypeLayoutUuid(layout.getUuid());
1119
1120 layoutId = LayoutLocalServiceUtil.getNextLayoutId(
1121 groupId, privateLayout);
1122 }
1123 else {
1124 importedLayout.setCreateDate(layout.getCreateDate());
1125 importedLayout.setModifiedDate(layout.getModifiedDate());
1126 importedLayout.setLayoutPrototypeUuid(
1127 layout.getLayoutPrototypeUuid());
1128 importedLayout.setLayoutPrototypeLinkEnabled(
1129 layout.isLayoutPrototypeLinkEnabled());
1130 importedLayout.setSourcePrototypeLayoutUuid(
1131 layout.getSourcePrototypeLayoutUuid());
1132 }
1133
1134 importedLayout.setUuid(layout.getUuid());
1135 importedLayout.setGroupId(groupId);
1136 importedLayout.setPrivateLayout(privateLayout);
1137 importedLayout.setLayoutId(layoutId);
1138
1139
1140
1141 boolean addGroupPermissions = true;
1142
1143 Group group = importedLayout.getGroup();
1144
1145 if (privateLayout && group.isUser()) {
1146 addGroupPermissions = false;
1147 }
1148
1149 boolean addGuestPermissions = false;
1150
1151 if (!privateLayout || layout.isTypeControlPanel()) {
1152 addGuestPermissions = true;
1153 }
1154
1155 ResourceLocalServiceUtil.addResources(
1156 user.getCompanyId(), groupId, user.getUserId(),
1157 Layout.class.getName(), importedLayout.getPlid(), false,
1158 addGroupPermissions, addGuestPermissions);
1159
1160 LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
1161 groupId, privateLayout);
1162
1163 importedLayout.setLayoutSet(layoutSet);
1164 }
1165 else {
1166 importedLayout = existingLayout;
1167 }
1168
1169 newLayoutsMap.put(oldLayoutId, importedLayout);
1170
1171 long parentLayoutId = layout.getParentLayoutId();
1172
1173 Node parentLayoutNode = rootElement.selectSingleNode(
1174 "./layouts/layout[@layout-id='" + parentLayoutId + "']");
1175
1176 String parentLayoutUuid = GetterUtil.getString(
1177 layoutElement.attributeValue("parent-layout-uuid"));
1178
1179 if ((parentLayoutId != LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) &&
1180 (parentLayoutNode != null)) {
1181
1182 importLayout(
1183 portletDataContext, user, layoutCache, previousLayouts,
1184 newLayouts, newLayoutsMap, portletsMergeMode, themeId,
1185 colorSchemeId, layoutsImportMode, privateLayout,
1186 importPermissions, importPublicLayoutPermissions,
1187 importThemeSettings, rootElement, (Element)parentLayoutNode);
1188
1189 Layout parentLayout = newLayoutsMap.get(parentLayoutId);
1190
1191 parentLayoutId = parentLayout.getLayoutId();
1192 }
1193 else if (Validator.isNotNull(parentLayoutUuid)) {
1194 Layout parentLayout =
1195 LayoutLocalServiceUtil.getLayoutByUuidAndGroupId(
1196 parentLayoutUuid, groupId, privateLayout);
1197
1198 parentLayoutId = parentLayout.getLayoutId();
1199 }
1200
1201 if (_log.isDebugEnabled()) {
1202 _log.debug(
1203 "Importing layout with layout id " + layoutId +
1204 " and parent layout id " + parentLayoutId);
1205 }
1206
1207 importedLayout.setCompanyId(user.getCompanyId());
1208 importedLayout.setParentLayoutId(parentLayoutId);
1209 importedLayout.setName(layout.getName());
1210 importedLayout.setTitle(layout.getTitle());
1211 importedLayout.setDescription(layout.getDescription());
1212 importedLayout.setKeywords(layout.getKeywords());
1213 importedLayout.setRobots(layout.getRobots());
1214 importedLayout.setType(layout.getType());
1215
1216 if (layout.isTypeArticle()) {
1217 importJournalArticle(portletDataContext, layout, layoutElement);
1218
1219 updateTypeSettings(importedLayout, layout);
1220 }
1221 else if (layout.isTypePortlet() &&
1222 Validator.isNotNull(layout.getTypeSettings()) &&
1223 !portletsMergeMode.equals(
1224 PortletDataHandlerKeys.PORTLETS_MERGE_MODE_REPLACE)) {
1225
1226 mergePortlets(
1227 importedLayout, layout.getTypeSettings(), portletsMergeMode);
1228 }
1229 else if (layout.isTypeLinkToLayout()) {
1230 UnicodeProperties typeSettingsProperties =
1231 layout.getTypeSettingsProperties();
1232
1233 long linkToLayoutId = GetterUtil.getLong(
1234 typeSettingsProperties.getProperty(
1235 "linkToLayoutId", StringPool.BLANK));
1236
1237 if (linkToLayoutId > 0) {
1238 Node linkedLayoutNode = rootElement.selectSingleNode(
1239 "./layouts/layout[@layout-id='" + linkToLayoutId + "']");
1240
1241 if (linkedLayoutNode != null) {
1242 importLayout(
1243 portletDataContext, user, layoutCache, previousLayouts,
1244 newLayouts, newLayoutsMap, portletsMergeMode, themeId,
1245 colorSchemeId, layoutsImportMode, privateLayout,
1246 importPermissions, importPublicLayoutPermissions,
1247 importThemeSettings, rootElement,
1248 (Element)linkedLayoutNode);
1249
1250 Layout linkedLayout = newLayoutsMap.get(linkToLayoutId);
1251
1252 typeSettingsProperties.setProperty(
1253 "privateLayout",
1254 String.valueOf(linkedLayout.isPrivateLayout()));
1255 typeSettingsProperties.setProperty(
1256 "linkToLayoutId",
1257 String.valueOf(linkedLayout.getLayoutId()));
1258 }
1259 else {
1260 if (_log.isWarnEnabled()) {
1261 StringBundler sb = new StringBundler();
1262
1263 sb.append("Unable to link layout with friendly URL ");
1264 sb.append(layout.getFriendlyURL());
1265 sb.append(" and layout id ");
1266 sb.append(layout.getLayoutId());
1267 sb.append(" to layout with layout id ");
1268 sb.append(linkToLayoutId);
1269
1270 _log.warn(sb.toString());
1271 }
1272 }
1273 }
1274
1275 updateTypeSettings(importedLayout, layout);
1276 }
1277 else {
1278 updateTypeSettings(importedLayout, layout);
1279 }
1280
1281 importedLayout.setHidden(layout.isHidden());
1282 importedLayout.setFriendlyURL(friendlyURL);
1283
1284 if (importThemeSettings) {
1285 importedLayout.setThemeId(layout.getThemeId());
1286 importedLayout.setColorSchemeId(layout.getColorSchemeId());
1287 }
1288 else {
1289 importedLayout.setThemeId(StringPool.BLANK);
1290 importedLayout.setColorSchemeId(StringPool.BLANK);
1291 }
1292
1293 importedLayout.setWapThemeId(layout.getWapThemeId());
1294 importedLayout.setWapColorSchemeId(layout.getWapColorSchemeId());
1295 importedLayout.setCss(layout.getCss());
1296 importedLayout.setPriority(layout.getPriority());
1297 importedLayout.setLayoutPrototypeUuid(layout.getLayoutPrototypeUuid());
1298 importedLayout.setLayoutPrototypeLinkEnabled(
1299 layout.isLayoutPrototypeLinkEnabled());
1300
1301 StagingUtil.updateLastImportSettings(
1302 layoutElement, importedLayout, portletDataContext);
1303
1304 fixTypeSettings(importedLayout);
1305
1306 importedLayout.setIconImage(false);
1307
1308 if (layout.isIconImage()) {
1309 String iconImagePath = layoutElement.elementText("icon-image-path");
1310
1311 byte[] iconBytes = portletDataContext.getZipEntryAsByteArray(
1312 iconImagePath);
1313
1314 if ((iconBytes != null) && (iconBytes.length > 0)) {
1315 importedLayout.setIconImage(true);
1316
1317 if (importedLayout.getIconImageId() == 0) {
1318 long iconImageId = CounterLocalServiceUtil.increment();
1319
1320 importedLayout.setIconImageId(iconImageId);
1321 }
1322
1323 ImageLocalServiceUtil.updateImage(
1324 importedLayout.getIconImageId(), iconBytes);
1325 }
1326 }
1327 else {
1328 ImageLocalServiceUtil.deleteImage(importedLayout.getIconImageId());
1329 }
1330
1331 ServiceContext serviceContext = portletDataContext.createServiceContext(
1332 layoutElement, importedLayout, null);
1333
1334 importedLayout.setExpandoBridgeAttributes(serviceContext);
1335
1336 LayoutUtil.update(importedLayout);
1337
1338 portletDataContext.setPlid(importedLayout.getPlid());
1339 portletDataContext.setOldPlid(layout.getPlid());
1340
1341 newLayouts.add(importedLayout);
1342
1343
1344
1345 if (importPermissions) {
1346 _permissionImporter.importLayoutPermissions(
1347 layoutCache, portletDataContext.getCompanyId(), groupId,
1348 user.getUserId(), importedLayout, layoutElement, rootElement);
1349 }
1350
1351 if (importPublicLayoutPermissions) {
1352 String resourceName = Layout.class.getName();
1353 String resourcePrimKey = String.valueOf(importedLayout.getPlid());
1354
1355 Role guestRole = RoleLocalServiceUtil.getRole(
1356 importedLayout.getCompanyId(), RoleConstants.GUEST);
1357
1358 ResourcePermissionLocalServiceUtil.setResourcePermissions(
1359 importedLayout.getCompanyId(), resourceName,
1360 ResourceConstants.SCOPE_INDIVIDUAL, resourcePrimKey,
1361 guestRole.getRoleId(), new String[] {ActionKeys.VIEW});
1362 }
1363
1364 _portletImporter.importPortletData(
1365 portletDataContext, PortletKeys.LAYOUT_CONFIGURATION, null,
1366 layoutElement);
1367 }
1368
1369 protected void importLayoutSetPrototype(
1370 PortletDataContext portletDataContext, User user,
1371 String layoutSetPrototypeUuid, ServiceContext serviceContext)
1372 throws PortalException, SystemException {
1373
1374 String path = getLayoutSetPrototype(
1375 portletDataContext, layoutSetPrototypeUuid);
1376
1377 LayoutSetPrototype layoutSetPrototype = null;
1378
1379 try {
1380 layoutSetPrototype =
1381 LayoutSetPrototypeLocalServiceUtil.
1382 getLayoutSetPrototypeByUuidAndCompanyId(
1383 layoutSetPrototypeUuid, serviceContext.getCompanyId());
1384 }
1385 catch (NoSuchLayoutSetPrototypeException nslspe) {
1386 }
1387
1388 if (layoutSetPrototype == null) {
1389 layoutSetPrototype =
1390 (LayoutSetPrototype)portletDataContext.getZipEntryAsObject(
1391 path.concat(".xml"));
1392
1393 serviceContext.setUuid(layoutSetPrototypeUuid);
1394
1395 layoutSetPrototype =
1396 LayoutSetPrototypeLocalServiceUtil.addLayoutSetPrototype(
1397 user.getUserId(), user.getCompanyId(),
1398 layoutSetPrototype.getNameMap(),
1399 layoutSetPrototype.getDescription(),
1400 layoutSetPrototype.getActive(), true, serviceContext);
1401 }
1402
1403 InputStream inputStream = portletDataContext.getZipEntryAsInputStream(
1404 path.concat(".lar"));
1405
1406 SitesUtil.importLayoutSetPrototype(
1407 layoutSetPrototype, inputStream, serviceContext);
1408 }
1409
1410 protected String importTheme(LayoutSet layoutSet, InputStream themeZip)
1411 throws Exception {
1412
1413 ThemeLoader themeLoader = ThemeLoaderFactory.getDefaultThemeLoader();
1414
1415 if (themeLoader == null) {
1416 _log.error("No theme loaders are deployed");
1417
1418 return null;
1419 }
1420
1421 ZipReader zipReader = ZipReaderFactoryUtil.getZipReader(themeZip);
1422
1423 String lookAndFeelXML = zipReader.getEntryAsString(
1424 "liferay-look-and-feel.xml");
1425
1426 String themeId = String.valueOf(layoutSet.getGroupId());
1427
1428 if (layoutSet.isPrivateLayout()) {
1429 themeId += "-private";
1430 }
1431 else {
1432 themeId += "-public";
1433 }
1434
1435 if (PropsValues.THEME_LOADER_NEW_THEME_ID_ON_IMPORT) {
1436 Date now = new Date();
1437
1438 themeId += "-" + Time.getShortTimestamp(now);
1439 }
1440
1441 String themeName = themeId;
1442
1443 lookAndFeelXML = StringUtil.replace(
1444 lookAndFeelXML,
1445 new String[] {
1446 "[$GROUP_ID$]", "[$THEME_ID$]", "[$THEME_NAME$]"
1447 },
1448 new String[] {
1449 String.valueOf(layoutSet.getGroupId()), themeId, themeName
1450 }
1451 );
1452
1453 FileUtil.deltree(
1454 themeLoader.getFileStorage() + StringPool.SLASH + themeId);
1455
1456 List<String> zipEntries = zipReader.getEntries();
1457
1458 for (String zipEntry : zipEntries) {
1459 String key = zipEntry;
1460
1461 if (key.equals("liferay-look-and-feel.xml")) {
1462 FileUtil.write(
1463 themeLoader.getFileStorage() + StringPool.SLASH + themeId +
1464 StringPool.SLASH + key,
1465 lookAndFeelXML.getBytes());
1466 }
1467 else {
1468 InputStream is = zipReader.getEntryAsInputStream(zipEntry);
1469
1470 FileUtil.write(
1471 themeLoader.getFileStorage() + StringPool.SLASH + themeId +
1472 StringPool.SLASH + key,
1473 is);
1474 }
1475 }
1476
1477 themeLoader.loadThemes();
1478
1479 ClusterRequest clusterRequest = ClusterRequest.createMulticastRequest(
1480 _loadThemesMethodHandler, true);
1481
1482 clusterRequest.setFireAndForget(true);
1483
1484 ClusterExecutorUtil.execute(clusterRequest);
1485
1486 themeId +=
1487 PortletConstants.WAR_SEPARATOR +
1488 themeLoader.getServletContextName();
1489
1490 return PortalUtil.getJsSafePortletId(themeId);
1491 }
1492
1493 protected void mergePortlets(
1494 Layout layout, String newTypeSettings, String portletsMergeMode) {
1495
1496 try {
1497 UnicodeProperties previousTypeSettingsProperties =
1498 layout.getTypeSettingsProperties();
1499
1500 LayoutTypePortlet previousLayoutType =
1501 (LayoutTypePortlet)layout.getLayoutType();
1502
1503 LayoutTemplate previousLayoutTemplate =
1504 previousLayoutType.getLayoutTemplate();
1505
1506 List<String> previousColumns = previousLayoutTemplate.getColumns();
1507
1508 UnicodeProperties newTypeSettingsProperties = new UnicodeProperties(
1509 true);
1510
1511 newTypeSettingsProperties.load(newTypeSettings);
1512
1513 String layoutTemplateId = newTypeSettingsProperties.getProperty(
1514 LayoutTypePortletConstants.LAYOUT_TEMPLATE_ID);
1515
1516 previousTypeSettingsProperties.setProperty(
1517 LayoutTypePortletConstants.LAYOUT_TEMPLATE_ID,
1518 layoutTemplateId);
1519
1520 String nestedColumnIds = newTypeSettingsProperties.getProperty(
1521 LayoutTypePortletConstants.NESTED_COLUMN_IDS);
1522
1523 if (Validator.isNotNull(nestedColumnIds)) {
1524 previousTypeSettingsProperties.setProperty(
1525 LayoutTypePortletConstants.NESTED_COLUMN_IDS,
1526 nestedColumnIds);
1527
1528 String[] nestedColumnIdsArray = StringUtil.split(
1529 nestedColumnIds);
1530
1531 for (String nestedColumnId : nestedColumnIdsArray) {
1532 String nestedColumnValue =
1533 newTypeSettingsProperties.getProperty(nestedColumnId);
1534
1535 previousTypeSettingsProperties.setProperty(
1536 nestedColumnId, nestedColumnValue);
1537 }
1538 }
1539
1540 LayoutTemplate newLayoutTemplate =
1541 LayoutTemplateLocalServiceUtil.getLayoutTemplate(
1542 layoutTemplateId, false, null);
1543
1544 String[] newPortletIds = new String[0];
1545
1546 for (String columnId : newLayoutTemplate.getColumns()) {
1547 String columnValue = newTypeSettingsProperties.getProperty(
1548 columnId);
1549
1550 String[] portletIds = StringUtil.split(columnValue);
1551
1552 if (!previousColumns.contains(columnId)) {
1553 newPortletIds = ArrayUtil.append(newPortletIds, portletIds);
1554 }
1555 else {
1556 String[] previousPortletIds = StringUtil.split(
1557 previousTypeSettingsProperties.getProperty(columnId));
1558
1559 portletIds = appendPortletIds(
1560 previousPortletIds, portletIds, portletsMergeMode);
1561
1562 previousTypeSettingsProperties.setProperty(
1563 columnId, StringUtil.merge(portletIds));
1564 }
1565 }
1566
1567
1568
1569 String columnId = previousColumns.get(0);
1570
1571 String[] portletIds = StringUtil.split(
1572 previousTypeSettingsProperties.getProperty(columnId));
1573
1574 appendPortletIds(portletIds, newPortletIds, portletsMergeMode);
1575
1576 previousTypeSettingsProperties.setProperty(
1577 columnId, StringUtil.merge(portletIds));
1578
1579 layout.setTypeSettings(previousTypeSettingsProperties.toString());
1580 }
1581 catch (IOException ioe) {
1582 layout.setTypeSettings(newTypeSettings);
1583 }
1584 }
1585
1586 protected void updateTypeSettings(Layout importedLayout, Layout layout)
1587 throws PortalException, SystemException {
1588
1589 LayoutTypePortlet importedLayoutType =
1590 (LayoutTypePortlet)importedLayout.getLayoutType();
1591
1592 List<String> importedPortletIds = importedLayoutType.getPortletIds();
1593
1594 LayoutTypePortlet layoutType =
1595 (LayoutTypePortlet)layout.getLayoutType();
1596
1597 importedPortletIds.removeAll(layoutType.getPortletIds());
1598
1599 if (!importedPortletIds.isEmpty()) {
1600 PortletLocalServiceUtil.deletePortlets(
1601 importedLayout.getCompanyId(),
1602 importedPortletIds.toArray(
1603 new String[importedPortletIds.size()]),
1604 importedLayout.getPlid());
1605 }
1606
1607 importedLayout.setTypeSettings(layout.getTypeSettings());
1608 }
1609
1610 protected void validateLayoutPrototypes(
1611 long companyId, Element layoutsElement,
1612 List<Element> layoutElements)
1613 throws Exception {
1614
1615 List<Tuple> missingLayoutPrototypes = new ArrayList<Tuple>();
1616
1617 String layoutSetPrototypeUuid = layoutsElement.attributeValue(
1618 "layout-set-prototype-uuid");
1619
1620 if (Validator.isNotNull(layoutSetPrototypeUuid)) {
1621 try {
1622 LayoutSetPrototypeLocalServiceUtil.
1623 getLayoutSetPrototypeByUuidAndCompanyId(
1624 layoutSetPrototypeUuid, companyId);
1625 }
1626 catch (NoSuchLayoutSetPrototypeException nlspe) {
1627 String layoutSetPrototypeName = layoutsElement.attributeValue(
1628 "layout-set-prototype-name");
1629
1630 missingLayoutPrototypes.add(
1631 new Tuple(
1632 LayoutSetPrototype.class.getName(),
1633 layoutSetPrototypeUuid, layoutSetPrototypeName));
1634 }
1635 }
1636
1637 for (Element layoutElement : layoutElements) {
1638 String layoutPrototypeUuid = GetterUtil.getString(
1639 layoutElement.attributeValue("layout-prototype-uuid"));
1640
1641 if (Validator.isNotNull(layoutPrototypeUuid)) {
1642 try {
1643 LayoutPrototypeLocalServiceUtil.
1644 getLayoutPrototypeByUuidAndCompanyId(
1645 layoutPrototypeUuid, companyId);
1646 }
1647 catch (NoSuchLayoutPrototypeException nslpe) {
1648 String layoutPrototypeName = GetterUtil.getString(
1649 layoutElement.attributeValue("layout-prototype-name"));
1650
1651 missingLayoutPrototypes.add(
1652 new Tuple(
1653 LayoutPrototype.class.getName(),
1654 layoutPrototypeUuid, layoutPrototypeName));
1655 }
1656 }
1657 }
1658
1659 if (!missingLayoutPrototypes.isEmpty()) {
1660 throw new LayoutPrototypeException(missingLayoutPrototypes);
1661 }
1662 }
1663
1664 private static Log _log = LogFactoryUtil.getLog(LayoutImporter.class);
1665
1666 private static MethodHandler _loadThemesMethodHandler = new MethodHandler(
1667 new MethodKey(ThemeLoaderFactory.class, "loadThemes"));
1668
1669 private PermissionImporter _permissionImporter = new PermissionImporter();
1670 private PortletImporter _portletImporter = new PortletImporter();
1671
1672 }