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