1   /**
2    * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.service.impl;
24  
25  import com.liferay.portal.LayoutFriendlyURLException;
26  import com.liferay.portal.LayoutHiddenException;
27  import com.liferay.portal.LayoutImportException;
28  import com.liferay.portal.LayoutParentLayoutIdException;
29  import com.liferay.portal.LayoutTypeException;
30  import com.liferay.portal.NoSuchLayoutException;
31  import com.liferay.portal.NoSuchPortletPreferencesException;
32  import com.liferay.portal.PortalException;
33  import com.liferay.portal.RequiredLayoutException;
34  import com.liferay.portal.SystemException;
35  import com.liferay.portal.comm.CommLink;
36  import com.liferay.portal.kernel.language.LanguageUtil;
37  import com.liferay.portal.kernel.lar.PortletDataContext;
38  import com.liferay.portal.kernel.lar.PortletDataHandler;
39  import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
40  import com.liferay.portal.kernel.lar.UserIdStrategy;
41  import com.liferay.portal.kernel.portlet.FriendlyURLMapper;
42  import com.liferay.portal.kernel.util.GetterUtil;
43  import com.liferay.portal.kernel.util.LocaleUtil;
44  import com.liferay.portal.kernel.util.MethodWrapper;
45  import com.liferay.portal.kernel.util.StringPool;
46  import com.liferay.portal.kernel.util.StringUtil;
47  import com.liferay.portal.kernel.util.Validator;
48  import com.liferay.portal.kernel.zip.ZipReader;
49  import com.liferay.portal.kernel.zip.ZipWriter;
50  import com.liferay.portal.lar.AlwaysCurrentUserIdStrategy;
51  import com.liferay.portal.lar.CurrentUserIdStrategy;
52  import com.liferay.portal.lar.PortletDataContextImpl;
53  import com.liferay.portal.model.Group;
54  import com.liferay.portal.model.Layout;
55  import com.liferay.portal.model.LayoutReference;
56  import com.liferay.portal.model.LayoutSet;
57  import com.liferay.portal.model.LayoutTypePortlet;
58  import com.liferay.portal.model.Portlet;
59  import com.liferay.portal.model.PortletPreferences;
60  import com.liferay.portal.model.Resource;
61  import com.liferay.portal.model.Role;
62  import com.liferay.portal.model.Theme;
63  import com.liferay.portal.model.User;
64  import com.liferay.portal.model.impl.ColorSchemeImpl;
65  import com.liferay.portal.model.impl.GroupImpl;
66  import com.liferay.portal.model.impl.LayoutImpl;
67  import com.liferay.portal.model.impl.PortletImpl;
68  import com.liferay.portal.model.impl.ResourceImpl;
69  import com.liferay.portal.security.permission.ResourceActionsUtil;
70  import com.liferay.portal.service.LayoutLocalServiceUtil;
71  import com.liferay.portal.service.base.LayoutLocalServiceBaseImpl;
72  import com.liferay.portal.service.permission.PortletPermissionUtil;
73  import com.liferay.portal.theme.ThemeLoader;
74  import com.liferay.portal.theme.ThemeLoaderFactory;
75  import com.liferay.portal.util.ContentUtil;
76  import com.liferay.portal.util.PortalUtil;
77  import com.liferay.portal.util.PortletKeys;
78  import com.liferay.portal.util.PropsValues;
79  import com.liferay.portal.util.ReleaseInfo;
80  import com.liferay.portal.util.comparator.LayoutPriorityComparator;
81  import com.liferay.portal.velocity.VelocityContextPool;
82  import com.liferay.portlet.PortletPreferencesImpl;
83  import com.liferay.portlet.PortletPreferencesSerializer;
84  import com.liferay.portlet.documentlibrary.NoSuchFolderException;
85  import com.liferay.portlet.documentlibrary.model.DLFolder;
86  import com.liferay.portlet.documentlibrary.model.impl.DLFolderImpl;
87  import com.liferay.util.CollectionFactory;
88  import com.liferay.util.FileUtil;
89  import com.liferay.util.MapUtil;
90  import com.liferay.util.Normalizer;
91  import com.liferay.util.Time;
92  import com.liferay.util.xml.XMLFormatter;
93  
94  import com.thoughtworks.xstream.XStream;
95  
96  import java.io.ByteArrayInputStream;
97  import java.io.File;
98  import java.io.FileInputStream;
99  import java.io.FileNotFoundException;
100 import java.io.IOException;
101 import java.io.InputStream;
102 import java.io.StringReader;
103 
104 import java.util.ArrayList;
105 import java.util.Collections;
106 import java.util.Date;
107 import java.util.HashMap;
108 import java.util.Iterator;
109 import java.util.LinkedHashMap;
110 import java.util.LinkedHashSet;
111 import java.util.List;
112 import java.util.Locale;
113 import java.util.Map;
114 import java.util.Properties;
115 import java.util.Set;
116 
117 import javax.servlet.ServletContext;
118 
119 import org.apache.commons.lang.time.StopWatch;
120 import org.apache.commons.logging.Log;
121 import org.apache.commons.logging.LogFactory;
122 
123 import org.dom4j.Document;
124 import org.dom4j.DocumentHelper;
125 import org.dom4j.Element;
126 import org.dom4j.io.SAXReader;
127 
128 /**
129  * <a href="LayoutLocalServiceImpl.java.html"><b><i>View Source</i></b></a>
130  *
131  * @author Brian Wing Shun Chan
132  * @author Joel Kozikowski
133  * @author Charles May
134  * @author Raymond Augé
135  * @author Jorge Ferrer
136  * @author Bruno Farache
137  *
138  */
139 public class LayoutLocalServiceImpl extends LayoutLocalServiceBaseImpl {
140 
141     public Layout addLayout(
142             long userId, long groupId, boolean privateLayout,
143             long parentLayoutId, String name, String title, String description,
144             String type, boolean hidden, String friendlyURL)
145         throws PortalException, SystemException {
146 
147         Map localeNamesMap = new HashMap();
148 
149         Locale defaultLocale = LocaleUtil.getDefault();
150 
151         localeNamesMap.put(defaultLocale, name);
152 
153         return addLayout(
154             userId, groupId, privateLayout, parentLayoutId, localeNamesMap,
155             new HashMap(), description, type, hidden, friendlyURL);
156     }
157 
158     public Layout addLayout(
159             long userId, long groupId, boolean privateLayout,
160             long parentLayoutId, Map localeNamesMap, Map localeTitlesMap,
161             String description, String type, boolean hidden, String friendlyURL)
162         throws PortalException, SystemException {
163 
164         return addLayout(
165             userId, groupId, privateLayout, parentLayoutId, localeNamesMap,
166             localeTitlesMap, description, type, hidden, friendlyURL,
167             DLFolderImpl.DEFAULT_PARENT_FOLDER_ID);
168     }
169 
170     public Layout addLayout(
171             long userId, long groupId, boolean privateLayout,
172             long parentLayoutId, String name, String title, String description,
173             String type, boolean hidden, String friendlyURL, long dlFolderId)
174         throws PortalException, SystemException {
175 
176         Map localeNamesMap = new HashMap();
177 
178         Locale defaultLocale = LocaleUtil.getDefault();
179 
180         localeNamesMap.put(defaultLocale, name);
181 
182         return addLayout(
183             userId, groupId, privateLayout, parentLayoutId, localeNamesMap,
184             new HashMap(), description, type, hidden, friendlyURL, dlFolderId);
185     }
186 
187     public Layout addLayout(
188             long userId, long groupId, boolean privateLayout,
189             long parentLayoutId, Map localeNamesMap, Map localeTitlesMap,
190             String description, String type, boolean hidden, String friendlyURL,
191             long dlFolderId)
192         throws PortalException, SystemException {
193 
194         // Layout
195 
196         User user = userPersistence.findByPrimaryKey(userId);
197         long layoutId = getNextLayoutId(groupId, privateLayout);
198         parentLayoutId = getParentLayoutId(
199             groupId, privateLayout, parentLayoutId);
200         friendlyURL = getFriendlyURL(friendlyURL);
201         int priority = getNextPriority(groupId, privateLayout, parentLayoutId);
202 
203         validate(
204             groupId, privateLayout, layoutId, parentLayoutId, type, hidden,
205             friendlyURL);
206 
207         long plid = counterLocalService.increment();
208 
209         Layout layout = layoutPersistence.create(plid);
210 
211         layout.setGroupId(groupId);
212         layout.setCompanyId(user.getCompanyId());
213         layout.setPrivateLayout(privateLayout);
214         layout.setLayoutId(layoutId);
215         layout.setParentLayoutId(parentLayoutId);
216         layout.setDescription(description);
217         layout.setType(type);
218         layout.setHidden(hidden);
219         layout.setFriendlyURL(friendlyURL);
220         layout.setPriority(priority);
221         layout.setDlFolderId(dlFolderId);
222 
223         setLocalizedAttributes(layout, localeNamesMap, localeTitlesMap);
224 
225         layoutPersistence.update(layout);
226 
227         // Resources
228 
229         resourceLocalService.addResources(
230             user.getCompanyId(), groupId, user.getUserId(),
231             Layout.class.getName(), layout.getPlid(), false, true, true);
232 
233         // Layout set
234 
235         layoutSetLocalService.updatePageCount(groupId, privateLayout);
236 
237         return layout;
238     }
239 
240     public void deleteLayout(long plid)
241         throws PortalException, SystemException {
242 
243         Layout layout = layoutPersistence.findByPrimaryKey(plid);
244 
245         deleteLayout(layout, true);
246     }
247 
248     public void deleteLayout(long groupId, boolean privateLayout, long layoutId)
249         throws PortalException, SystemException {
250 
251         Layout layout = layoutPersistence.findByG_P_L(
252             groupId, privateLayout, layoutId);
253 
254         deleteLayout(layout, true);
255     }
256 
257     public void deleteLayout(Layout layout, boolean updateLayoutSet)
258         throws PortalException, SystemException {
259 
260         // Child layouts
261 
262         List childLayouts = layoutPersistence.findByG_P_P(
263             layout.getGroupId(), layout.isPrivateLayout(),
264             layout.getLayoutId());
265 
266         for (int i = 0; i < childLayouts.size(); i++) {
267             Layout childLayout = (Layout)childLayouts.get(i);
268 
269             deleteLayout(childLayout, updateLayoutSet);
270         }
271 
272         // Portlet preferences
273 
274         portletPreferencesLocalService.deletePortletPreferences(
275             PortletKeys.PREFS_OWNER_ID_DEFAULT,
276             PortletKeys.PREFS_OWNER_TYPE_LAYOUT, layout.getPlid());
277 
278         // Ratings
279 
280         ratingsStatsLocalService.deleteStats(
281             Layout.class.getName(), layout.getPlid());
282 
283         // Message boards
284 
285         mbMessageLocalService.deleteDiscussionMessages(
286             Layout.class.getName(), layout.getPlid());
287 
288         // Journal content searches
289 
290         journalContentSearchLocalService.deleteLayoutContentSearches(
291             layout.getGroupId(), layout.isPrivateLayout(),
292             layout.getLayoutId());
293 
294         // Icon
295 
296         ImageLocalUtil.deleteImage(layout.getIconImageId());
297 
298         // Resources
299 
300         String primKey = layout.getPlid() + PortletImpl.LAYOUT_SEPARATOR + "%";
301 
302         Iterator itr = resourceFinder.findByC_P(
303             layout.getCompanyId(), primKey).iterator();
304 
305         while (itr.hasNext()) {
306             Resource resource = (Resource)itr.next();
307 
308             resourceLocalService.deleteResource(resource);
309         }
310 
311         resourceLocalService.deleteResource(
312             layout.getCompanyId(), Layout.class.getName(),
313             ResourceImpl.SCOPE_INDIVIDUAL, layout.getPlid());
314 
315         // Layout
316 
317         layoutPersistence.remove(layout.getPlid());
318 
319         // Layout set
320 
321         if (updateLayoutSet) {
322             layoutSetLocalService.updatePageCount(
323                 layout.getGroupId(), layout.isPrivateLayout());
324         }
325     }
326 
327     public void deleteLayouts(long groupId, boolean privateLayout)
328         throws PortalException, SystemException {
329 
330         // Layouts
331 
332         List layouts = layoutPersistence.findByG_P_P(
333             groupId, privateLayout, LayoutImpl.DEFAULT_PARENT_LAYOUT_ID);
334 
335         Iterator itr = layouts.iterator();
336 
337         while (itr.hasNext()) {
338             Layout layout = (Layout)itr.next();
339 
340             try {
341                 deleteLayout(layout, false);
342             }
343             catch (NoSuchLayoutException nsle) {
344             }
345         }
346 
347         // Layout set
348 
349         layoutSetLocalService.updatePageCount(groupId, privateLayout);
350     }
351 
352     public byte[] exportLayouts(
353             long groupId, boolean privateLayout, Map parameterMap)
354         throws PortalException, SystemException {
355 
356         return exportLayouts(groupId, privateLayout, null, parameterMap);
357     }
358 
359     public byte[] exportLayouts(
360             long groupId, boolean privateLayout, long[] layoutIds,
361             Map parameterMap)
362         throws PortalException, SystemException {
363 
364         boolean exportPermissions = MapUtil.getBoolean(
365             parameterMap, PortletDataHandlerKeys.PERMISSIONS);
366         boolean exportUserPermissions = MapUtil.getBoolean(
367             parameterMap, PortletDataHandlerKeys.USER_PERMISSIONS);
368         boolean exportPortletData = MapUtil.getBoolean(
369             parameterMap, PortletDataHandlerKeys.PORTLET_DATA);
370         boolean exportPortletSetup = MapUtil.getBoolean(
371             parameterMap, PortletDataHandlerKeys.PORTLET_SETUP);
372         boolean exportPortletUserPreferences = MapUtil.getBoolean(
373             parameterMap, PortletDataHandlerKeys.PORTLET_USER_PREFERENCES);
374         boolean exportTheme = MapUtil.getBoolean(
375             parameterMap, PortletDataHandlerKeys.THEME);
376 
377         if (_log.isDebugEnabled()) {
378             _log.debug("Export permissions " + exportPermissions);
379             _log.debug("Export user permissions " + exportUserPermissions);
380             _log.debug("Export portlet data " + exportPortletData);
381             _log.debug("Export portlet setup " + exportPortletSetup);
382             _log.debug(
383                 "Export portlet user preferences " +
384                     exportPortletUserPreferences);
385             _log.debug("Export theme " + exportTheme);
386         }
387 
388         StopWatch stopWatch = null;
389 
390         if (_log.isInfoEnabled()) {
391             stopWatch = new StopWatch();
392 
393             stopWatch.start();
394         }
395 
396         LayoutCache layoutCache = new LayoutCache();
397 
398         LayoutSet layoutSet = layoutSetLocalService.getLayoutSet(
399             groupId, privateLayout);
400 
401         long companyId = layoutSet.getCompanyId();
402         long defaultUserId = userLocalService.getDefaultUserId(companyId);
403 
404         ZipWriter zipWriter = new ZipWriter();
405 
406         PortletDataContext context = new PortletDataContextImpl(
407             companyId, groupId, parameterMap, CollectionFactory.getHashSet(),
408             zipWriter);
409 
410         Group guestGroup = groupLocalService.getGroup(
411             companyId, GroupImpl.GUEST);
412 
413         // Build compatibility
414 
415         Document doc = DocumentHelper.createDocument();
416 
417         Element root = doc.addElement("root");
418 
419         Element header = root.addElement("header");
420 
421         header.addAttribute(
422             "build-number", String.valueOf(ReleaseInfo.getBuildNumber()));
423         header.addAttribute("group-id", String.valueOf(groupId));
424         header.addAttribute("private-layout", String.valueOf(privateLayout));
425         header.addAttribute("export-date", Time.getRFC822());
426         header.addAttribute("theme-id", layoutSet.getThemeId());
427         header.addAttribute("color-scheme-id", layoutSet.getColorSchemeId());
428         header.addAttribute("type", "layouts");
429 
430         // Layouts
431 
432         Set portletIds = new LinkedHashSet();
433 
434         List layouts = null;
435 
436         if ((layoutIds == null) || (layoutIds.length == 0)) {
437             layouts = getLayouts(groupId, privateLayout);
438         }
439         else {
440             layouts = getLayouts(groupId, privateLayout, layoutIds);
441         }
442 
443         Iterator itr = layouts.iterator();
444 
445         while (itr.hasNext()) {
446             Layout layout = (Layout)itr.next();
447 
448             context.setPlid(layout.getPlid());
449 
450             Element layoutEl = root.addElement("layout");
451 
452             layoutEl.addAttribute(
453                 "layout-id", String.valueOf(layout.getLayoutId()));
454             layoutEl.addElement("parent-layout-id").addText(
455                 String.valueOf(layout.getParentLayoutId()));
456             layoutEl.addElement("name").addCDATA(layout.getName());
457             layoutEl.addElement("title").addCDATA(layout.getTitle());
458             layoutEl.addElement("type").addText(layout.getType());
459             layoutEl.addElement("type-settings").addCDATA(
460                 layout.getTypeSettings());
461             layoutEl.addElement("hidden").addText(
462                 String.valueOf(layout.getHidden()));
463             layoutEl.addElement("friendly-url").addText(
464                 layout.getFriendlyURL());
465             layoutEl.addElement("theme-id").addText(layout.getThemeId());
466             layoutEl.addElement("color-scheme-id").addText(
467                 layout.getColorSchemeId());
468             layoutEl.addElement("priority").addText(
469                 String.valueOf(layout.getPriority()));
470 
471             Element permissionsEl = layoutEl.addElement("permissions");
472 
473             // Layout permissions
474 
475             if (exportPermissions) {
476                 exportLayoutPermissions(
477                     layoutCache, companyId, groupId, guestGroup, layout,
478                     permissionsEl, exportUserPermissions);
479             }
480 
481             if (layout.getType().equals(LayoutImpl.TYPE_PORTLET)) {
482                 LayoutTypePortlet layoutTypePortlet =
483                     (LayoutTypePortlet)layout.getLayoutType();
484 
485                 // The order of the export is important. You must always export
486                 // the portlet data first, then the portlet preferences, then
487                 // the portlet permissions. The export of the portlet data
488                 // process may modify the portlet preferences, and those changes
489                 // should be included in the exported LAR.
490 
491                 // Portlet data
492 
493                 if (exportPortletData) {
494                     exportPortletData(
495                         context, layout, layoutTypePortlet, layoutEl);
496                 }
497 
498                 // Portlet preferences
499 
500                 if (exportPortletSetup) {
501                     exportPortletPreferences(
502                         PortletKeys.PREFS_OWNER_ID_DEFAULT,
503                         PortletKeys.PREFS_OWNER_TYPE_LAYOUT, false,
504                         layout.getPlid(), layoutTypePortlet, layoutEl);
505 
506                     exportPortletPreferences(
507                         layout.getGroupId(),
508                         PortletKeys.PREFS_OWNER_TYPE_GROUP, false,
509                         layout.getPlid(), layoutTypePortlet, layoutEl);
510 
511                     exportPortletPreferences(
512                         layout.getCompanyId(),
513                         PortletKeys.PREFS_OWNER_TYPE_COMPANY, false,
514                         layout.getPlid(), layoutTypePortlet, layoutEl);
515                 }
516 
517                 if (exportPortletUserPreferences) {
518                     exportPortletPreferences(
519                         defaultUserId, PortletKeys.PREFS_OWNER_TYPE_USER,
520                         true, layout.getPlid(), layoutTypePortlet,
521                         layoutEl);
522                 }
523 
524                 // Portlet permissions
525 
526                 if (exportPermissions) {
527                     exportPortletPermissions(
528                         layoutCache, companyId, groupId, guestGroup,
529                         layout, layoutTypePortlet, portletIds, permissionsEl,
530                         exportUserPermissions);
531                 }
532             }
533         }
534 
535         // Portlet preferences
536 
537         if (exportPortletUserPreferences) {
538             exportPortletPreferences(
539                 groupId, PortletKeys.PREFS_OWNER_TYPE_GROUP,
540                 PortletKeys.PREFS_PLID_SHARED, false, root);
541 
542         }
543 
544         Element rolesEl = root.addElement("roles");
545 
546         // Layout roles
547 
548         if (exportPermissions) {
549             exportLayoutRoles(layoutCache, companyId, groupId, rolesEl);
550         }
551 
552         // Portlet roles
553 
554         if (exportPermissions) {
555             exportPortletRoles(
556                 layoutCache, companyId, groupId, portletIds, rolesEl);
557         }
558 
559         // Comments
560 
561         exportComments(context, root);
562 
563         // Ratings
564 
565         exportRatings(context, root);
566 
567         // Tags
568 
569         exportTags(context, root);
570 
571         // Look and feel
572 
573         byte[] themeZip = null;
574 
575         try {
576             if (exportTheme) {
577                 themeZip = exportTheme(layoutSet);
578             }
579         }
580         catch (IOException ioe) {
581             throw new SystemException(ioe);
582         }
583 
584         // XML
585 
586         if (_log.isInfoEnabled()) {
587             _log.info("Exporting layouts takes " + stopWatch.getTime() + " ms");
588         }
589 
590         // Zip
591 
592         try {
593             zipWriter.addEntry("layouts.xml", XMLFormatter.toString(doc));
594 
595             if (themeZip != null) {
596                 zipWriter.addEntry("theme.zip", themeZip);
597             }
598 
599             return zipWriter.finish();
600         }
601         catch (IOException ioe) {
602             throw new SystemException(ioe);
603         }
604     }
605 
606     public byte[] exportPortletInfo(
607             long plid, String portletId, Map parameterMap)
608         throws PortalException, SystemException {
609 
610         boolean exportPortletSetup = MapUtil.getBoolean(
611             parameterMap, PortletDataHandlerKeys.PORTLET_SETUP);
612         boolean exportPortletUserPreferences = MapUtil.getBoolean(
613             parameterMap, PortletDataHandlerKeys.PORTLET_USER_PREFERENCES);
614 
615         StopWatch stopWatch = null;
616 
617         if (_log.isInfoEnabled()) {
618             stopWatch = new StopWatch();
619 
620             stopWatch.start();
621         }
622 
623         Layout layout = LayoutLocalServiceUtil.getLayout(plid);
624 
625         if (!layout.getType().equals(LayoutImpl.TYPE_PORTLET)) {
626             throw new LayoutImportException(
627                 "Layout type " + layout.getType() + " is not valid");
628         }
629 
630         LayoutTypePortlet layoutTypePortlet =
631             (LayoutTypePortlet)layout.getLayoutType();
632 
633         if (!layoutTypePortlet.hasPortletId(portletId)) {
634             throw new LayoutImportException(
635                 "The specified layout does not have portlet " + portletId);
636         }
637 
638         long companyId = layout.getCompanyId();
639         long defaultUserId = userLocalService.getDefaultUserId(companyId);
640 
641         ZipWriter zipWriter = new ZipWriter();
642 
643         PortletDataContext context = new PortletDataContextImpl(
644             companyId, layout.getGroupId(), parameterMap,
645             CollectionFactory.getHashSet(), zipWriter);
646 
647         context.setPlid(plid);
648 
649         // Build compatibility
650 
651         Document doc = DocumentHelper.createDocument();
652 
653         Element root = doc.addElement("root");
654 
655         Element header = root.addElement("header");
656 
657         header.addAttribute(
658             "build-number", String.valueOf(ReleaseInfo.getBuildNumber()));
659         header.addAttribute("group-id", String.valueOf(layout.getGroupId()));
660         header.addAttribute("export-date", Time.getRFC822());
661         header.addAttribute("type", "portlet");
662 
663         // Data
664 
665         PortletPreferences portletPreferences = (PortletPreferences)
666             portletPreferencesLocalService.getPortletPreferences(plid).get(0);
667 
668         javax.portlet.PortletPreferences jxPrefs =
669             portletPreferencesLocalService.getPreferences(
670                 layout.getCompanyId(), portletPreferences.getOwnerId(),
671                 portletPreferences.getOwnerType(), plid, portletId);
672 
673         exportPortletData(context, portletId, jxPrefs, root);
674 
675         // Comments
676 
677         exportComments(context, root);
678 
679         // Ratings
680 
681         exportRatings(context, root);
682 
683         // Tags
684 
685         exportTags(context, root);
686 
687         // Portlet preferences
688 
689         if (exportPortletSetup) {
690             exportPortletPreferences(
691                 PortletKeys.PREFS_OWNER_ID_DEFAULT,
692                 PortletKeys.PREFS_OWNER_TYPE_LAYOUT, false, layout, portletId,
693                 root);
694 
695             exportPortletPreferences(
696                 layout.getGroupId(), PortletKeys.PREFS_OWNER_TYPE_GROUP, false,
697                 layout, portletId, root);
698 
699             exportPortletPreferences(
700                 layout.getCompanyId(), PortletKeys.PREFS_OWNER_TYPE_COMPANY,
701                 false, layout, portletId, root);
702         }
703 
704         if (exportPortletUserPreferences) {
705             exportPortletPreferences(
706                 defaultUserId, PortletKeys.PREFS_OWNER_TYPE_USER,
707                 true, layout, portletId, root);
708         }
709 
710         // XML
711 
712         if (_log.isInfoEnabled()) {
713             _log.info(
714                 "Exporting portlet info takes " + stopWatch.getTime() + " ms");
715         }
716 
717         // Zip
718 
719         try {
720             zipWriter.addEntry("portlet.xml", XMLFormatter.toString(doc));
721 
722             return zipWriter.finish();
723         }
724         catch (IOException ioe) {
725             throw new SystemException(ioe);
726         }
727     }
728 
729     public long getDefaultPlid(long groupId) throws SystemException {
730         if (groupId > 0) {
731             List layouts = layoutPersistence.findByGroupId(groupId, 0, 1);
732 
733             if (layouts.size() > 0) {
734                 Layout layout = (Layout)layouts.get(0);
735 
736                 return layout.getPlid();
737             }
738         }
739 
740         return LayoutImpl.DEFAULT_PLID;
741     }
742 
743     public long getDefaultPlid(long groupId, boolean privateLayout)
744         throws SystemException {
745 
746         if (groupId > 0) {
747             List layouts = layoutPersistence.findByG_P(
748                 groupId, privateLayout, 0, 1);
749 
750             if (layouts.size() > 0) {
751                 Layout layout = (Layout)layouts.get(0);
752 
753                 return layout.getPlid();
754             }
755         }
756 
757         return LayoutImpl.DEFAULT_PLID;
758     }
759 
760     public Layout getDLFolderLayout(long dlFolderId)
761         throws PortalException, SystemException {
762 
763         return layoutPersistence.findByDLFolderId(dlFolderId);
764     }
765 
766     public Layout getFriendlyURLLayout(
767             long groupId, boolean privateLayout, String friendlyURL)
768         throws PortalException, SystemException {
769 
770         if (Validator.isNull(friendlyURL)) {
771             throw new NoSuchLayoutException();
772         }
773 
774         friendlyURL = getFriendlyURL(friendlyURL);
775 
776         return layoutPersistence.findByG_P_F(
777             groupId, privateLayout, friendlyURL);
778     }
779 
780     public Layout getLayout(long plid)
781         throws PortalException, SystemException {
782 
783         return layoutPersistence.findByPrimaryKey(plid);
784     }
785 
786     public Layout getLayout(long groupId, boolean privateLayout, long layoutId)
787         throws PortalException, SystemException {
788 
789         return layoutPersistence.findByG_P_L(groupId, privateLayout, layoutId);
790     }
791 
792     public Layout getLayoutByIconImageId(long iconImageId)
793         throws PortalException, SystemException {
794 
795         return layoutPersistence.findByIconImageId(iconImageId);
796     }
797 
798     public List getLayouts(long groupId, boolean privateLayout)
799         throws SystemException {
800 
801         return layoutPersistence.findByG_P(groupId, privateLayout);
802     }
803 
804     public List getLayouts(
805             long groupId, boolean privateLayout, long parentLayoutId)
806         throws SystemException {
807 
808         return layoutPersistence.findByG_P_P(
809             groupId, privateLayout, parentLayoutId);
810     }
811 
812     public List getLayouts(
813             long groupId, boolean privateLayout, long parentLayoutId, int begin,
814             int end)
815         throws SystemException {
816 
817         return layoutPersistence.findByG_P_P(
818             groupId, privateLayout, parentLayoutId, begin, end);
819     }
820 
821     public List getLayouts(
822             long groupId, boolean privateLayout, long[] layoutIds)
823         throws PortalException, SystemException {
824 
825         List layouts = new ArrayList();
826 
827         for (int i = 0; i < layoutIds.length; i++) {
828             Layout layout = getLayout(groupId, privateLayout, layoutIds[i]);
829 
830             layouts.add(layout);
831         }
832 
833         return layouts;
834     }
835 
836     public LayoutReference[] getLayouts(
837             long companyId, String portletId, String prefsKey,
838             String prefsValue)
839         throws SystemException {
840 
841         List list = layoutFinder.findByC_P_P(
842             companyId, portletId, prefsKey, prefsValue);
843 
844         return (LayoutReference[])list.toArray(new LayoutReference[0]);
845     }
846 
847     public void importLayouts(
848             long userId, long groupId, boolean privateLayout, Map parameterMap,
849             File file)
850         throws PortalException, SystemException {
851 
852         try {
853             importLayouts(
854                 userId, groupId, privateLayout, parameterMap,
855                 new FileInputStream(file));
856         }
857         catch (FileNotFoundException fnfe) {
858             throw new SystemException(fnfe);
859         }
860     }
861 
862     public void importLayouts(
863             long userId, long groupId, boolean privateLayout, Map parameterMap,
864             InputStream is)
865         throws PortalException, SystemException {
866 
867         boolean deleteMissingLayouts = MapUtil.getBoolean(
868             parameterMap, PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
869             Boolean.TRUE.booleanValue());
870         boolean deletePortletData = MapUtil.getBoolean(
871             parameterMap, PortletDataHandlerKeys.DELETE_PORTLET_DATA);
872         boolean importPermissions = MapUtil.getBoolean(
873             parameterMap, PortletDataHandlerKeys.PERMISSIONS);
874         boolean importUserPermissions = MapUtil.getBoolean(
875             parameterMap, PortletDataHandlerKeys.PERMISSIONS);
876         boolean importPortletData = MapUtil.getBoolean(
877             parameterMap, PortletDataHandlerKeys.PORTLET_DATA);
878         boolean importPortletSetup = MapUtil.getBoolean(
879             parameterMap, PortletDataHandlerKeys.PORTLET_SETUP);
880         boolean importPortletUserPreferences = MapUtil.getBoolean(
881             parameterMap, PortletDataHandlerKeys.PORTLET_USER_PREFERENCES);
882         boolean importTheme = MapUtil.getBoolean(
883             parameterMap, PortletDataHandlerKeys.THEME);
884         String userIdStrategy = MapUtil.getString(
885             parameterMap, PortletDataHandlerKeys.USER_ID_STRATEGY);
886 
887         if (_log.isDebugEnabled()) {
888             _log.debug("Delete portlet data " + deletePortletData);
889             _log.debug("Import permissions " + importPermissions);
890             _log.debug("Import user permissions " + importUserPermissions);
891             _log.debug("Import portlet data " + importPortletData);
892             _log.debug("Import portlet setup " + importPortletSetup);
893             _log.debug(
894                 "Import portlet user preferences " +
895                     importPortletUserPreferences);
896             _log.debug("Import theme " + importTheme);
897         }
898 
899         StopWatch stopWatch = null;
900 
901         if (_log.isInfoEnabled()) {
902             stopWatch = new StopWatch();
903 
904             stopWatch.start();
905         }
906 
907         LayoutCache layoutCache = new LayoutCache();
908 
909         LayoutSet layoutSet = layoutSetLocalService.getLayoutSet(
910             groupId, privateLayout);
911 
912         long companyId = layoutSet.getCompanyId();
913 
914         User user = userPersistence.findByPrimaryKey(userId);
915 
916         // User ID strategy
917 
918         UserIdStrategy strategy = null;
919 
920         if (UserIdStrategy.ALWAYS_CURRENT_USER_ID.equals(userIdStrategy)) {
921             strategy = new AlwaysCurrentUserIdStrategy(user);
922         }
923         else if (UserIdStrategy.CURRENT_USER_ID.equals(userIdStrategy)) {
924             strategy = new CurrentUserIdStrategy(user);
925         }
926 
927         ZipReader zipReader = new ZipReader(is);
928 
929         PortletDataContext context = new PortletDataContextImpl(
930             companyId, groupId, parameterMap, CollectionFactory.getHashSet(),
931             strategy, zipReader);
932 
933         Group guestGroup = groupLocalService.getGroup(
934             companyId, GroupImpl.GUEST);
935 
936         // Zip
937 
938         Element root = null;
939         byte[] themeZip = null;
940 
941         try {
942 
943             // XML
944 
945             String xml = zipReader.getEntryAsString("layouts.xml");
946 
947             SAXReader reader = new SAXReader();
948 
949             Document doc = reader.read(new StringReader(xml));
950 
951             root = doc.getRootElement();
952 
953             // Look and feel
954 
955             if (importTheme) {
956                 themeZip = zipReader.getEntryAsByteArray("theme.zip");
957             }
958         }
959         catch (Exception e) {
960             throw new SystemException(e);
961         }
962 
963         // Build compatibility
964 
965         Element header = (Element)root.element("header");
966 
967         int buildNumber = ReleaseInfo.getBuildNumber();
968 
969         int importBuildNumber = GetterUtil.getInteger(
970             header.attributeValue("build-number"));
971 
972         if (buildNumber != importBuildNumber) {
973             throw new LayoutImportException(
974                 "LAR build number " + importBuildNumber + " does not match " +
975                     "portal build number " + buildNumber);
976         }
977 
978         // Look and feel
979 
980         String themeId = header.attributeValue("theme-id");
981         String colorSchemeId = header.attributeValue("color-scheme-id");
982 
983         boolean useThemeZip = false;
984 
985         if (themeZip != null) {
986             try {
987                 String importThemeId = importTheme(layoutSet, themeZip);
988 
989                 if (importThemeId != null) {
990                     themeId = importThemeId;
991                     colorSchemeId =
992                         ColorSchemeImpl.getDefaultRegularColorSchemeId();
993 
994                     useThemeZip = true;
995                 }
996 
997                 if (_log.isDebugEnabled()) {
998                     _log.debug(
999                         "Importing theme takes " + stopWatch.getTime() + " ms");
1000                }
1001            }
1002            catch (Exception e) {
1003                throw new SystemException(e);
1004            }
1005        }
1006
1007        boolean wapTheme = false;
1008
1009        layoutSetLocalService.updateLookAndFeel(
1010            groupId, privateLayout, themeId, colorSchemeId, StringPool.BLANK,
1011            wapTheme);
1012
1013        // Read comments, ratings, and tags to make them available to the data
1014        // handlers through the context
1015
1016        readComments(context, root);
1017        readRatings(context, root);
1018        readTags(context, root);
1019
1020        // Layouts
1021
1022        Set newLayoutIds = CollectionFactory.getHashSet();
1023
1024        Iterator itr = root.elements("layout").iterator();
1025
1026        if (_log.isDebugEnabled()) {
1027            if (itr.hasNext()) {
1028                _log.debug("Importing layouts");
1029            }
1030        }
1031
1032        while (itr.hasNext()) {
1033            Element layoutEl = (Element)itr.next();
1034
1035            long layoutId = GetterUtil.getInteger(
1036                layoutEl.attributeValue("layout-id"));
1037            long parentLayoutId = GetterUtil.getInteger(
1038                layoutEl.elementText("parent-layout-id"));
1039
1040            if (_log.isDebugEnabled()) {
1041                _log.debug(
1042                    "Importing layout with layout id " + layoutId +
1043                        " and parent layout id " + parentLayoutId);
1044            }
1045
1046            String name = layoutEl.elementText("name");
1047            String title = layoutEl.elementText("title");
1048            String type = layoutEl.elementText("type");
1049            String typeSettings = layoutEl.elementText("type-settings");
1050            boolean hidden = GetterUtil.getBoolean(
1051                layoutEl.elementText("hidden"));
1052            String friendlyURL = layoutEl.elementText("friendly-url");
1053
1054            if (useThemeZip) {
1055                themeId = StringPool.BLANK;
1056                colorSchemeId = StringPool.BLANK;
1057            }
1058            else {
1059                themeId = layoutEl.elementText("theme-id");
1060                colorSchemeId = layoutEl.elementText("color-scheme-id");
1061            }
1062
1063            int priority = GetterUtil.getInteger(
1064                layoutEl.elementText("priority"));
1065
1066            Layout layout = layoutPersistence.fetchByG_P_L(
1067                groupId, privateLayout, layoutId);
1068
1069            if (_log.isDebugEnabled()) {
1070                if (layout == null) {
1071                    _log.debug(
1072                        "Layout with {groupId=" + groupId + ",privateLayout=" +
1073                            privateLayout + ",layoutId=" + layoutId +
1074                                "} does not exist");
1075                }
1076                else {
1077                    _log.debug(
1078                        "Layout with {groupId=" + groupId + ",privateLayout=" +
1079                            privateLayout + ",layoutId=" + layoutId +
1080                                "} exists");
1081                }
1082            }
1083
1084            if (layout == null) {
1085                long plid = counterLocalService.increment();
1086
1087                layout = layoutPersistence.create(plid);
1088
1089                layout.setGroupId(groupId);
1090                layout.setPrivateLayout(privateLayout);
1091                layout.setLayoutId(layoutId);
1092            }
1093
1094            layout.setCompanyId(user.getCompanyId());
1095            layout.setParentLayoutId(parentLayoutId);
1096            layout.setName(name);
1097            layout.setTitle(title);
1098            layout.setType(type);
1099            layout.setTypeSettings(typeSettings);
1100            layout.setHidden(hidden);
1101            layout.setFriendlyURL(friendlyURL);
1102            layout.setThemeId(themeId);
1103            layout.setColorSchemeId(colorSchemeId);
1104            layout.setPriority(priority);
1105
1106            fixTypeSettings(layout);
1107
1108            layoutPersistence.update(layout);
1109
1110            context.setPlid(layout.getPlid());
1111
1112            newLayoutIds.add(new Long(layoutId));
1113
1114            Element permissionsEl = layoutEl.element("permissions");
1115
1116            // Layout permissions
1117
1118            if (importPermissions) {
1119                importLayoutPermissions(
1120                    layoutCache, companyId, groupId, guestGroup, layout,
1121                    permissionsEl, importUserPermissions);
1122            }
1123
1124            // The order of the import is important. You must always import
1125            // the portlet preferences first, then the portlet data, then
1126            // the portlet permissions. The import of the portlet data
1127            // assumes that portlet preferences already exist.
1128
1129            // Delete portlet data
1130
1131            if (deletePortletData) {
1132                deletePortletData(context, layout, layoutEl);
1133            }
1134
1135            // Portlet preferences
1136
1137            importPortletPreferences(
1138                layoutSet.getCompanyId(), layout.getPlid(), layoutEl,
1139                importPortletSetup, importPortletUserPreferences);
1140
1141            // Portlet data
1142
1143            if (importPortletData) {
1144                importPortletData(context, layout, layoutEl);
1145            }
1146
1147            // Portlet permissions
1148
1149            if (importPermissions) {
1150                importPortletPermissions(
1151                    layoutCache, companyId, groupId, guestGroup, layout,
1152                    permissionsEl, importUserPermissions);
1153            }
1154        }
1155
1156        Element rolesEl = (Element)root.element("roles");
1157
1158        // Layout roles
1159
1160        if (importPermissions) {
1161            importLayoutRoles(layoutCache, companyId, groupId, rolesEl);
1162        }
1163
1164        // Portlet roles
1165
1166        if (importPermissions) {
1167            importPortletRoles(layoutCache, companyId, groupId, rolesEl);
1168        }
1169
1170        // Delete missing layouts
1171
1172        if (deleteMissingLayouts) {
1173            deleteMissingLayouts(groupId, privateLayout, newLayoutIds);
1174        }
1175
1176        // Page count
1177
1178        layoutSetLocalService.updatePageCount(groupId, privateLayout);
1179
1180        if (_log.isInfoEnabled()) {
1181            _log.info("Importing layouts takes " + stopWatch.getTime() + " ms");
1182        }
1183    }
1184
1185    public void importPortletInfo(
1186            long userId, long plid, String portletId, Map parameterMap,
1187            File file)
1188        throws PortalException, SystemException {
1189
1190        try {
1191            importPortletInfo(
1192                userId, plid, portletId, parameterMap,
1193                new FileInputStream(file));
1194        }
1195        catch (FileNotFoundException fnfe) {
1196            throw new SystemException(fnfe);
1197        }
1198    }
1199
1200    public void importPortletInfo(
1201            long userId, long plid, String portletId, Map parameterMap,
1202            InputStream is)
1203        throws PortalException, SystemException {
1204
1205        boolean deletePortletData = MapUtil.getBoolean(
1206            parameterMap, PortletDataHandlerKeys.DELETE_PORTLET_DATA);
1207        boolean importPortletData = MapUtil.getBoolean(
1208            parameterMap, PortletDataHandlerKeys.PORTLET_DATA);
1209        boolean importPortletSetup = MapUtil.getBoolean(
1210            parameterMap, PortletDataHandlerKeys.PORTLET_SETUP);
1211        boolean importUserPreferences = MapUtil.getBoolean(
1212            parameterMap, PortletDataHandlerKeys.PORTLET_USER_PREFERENCES);
1213        String userIdStrategy = MapUtil.getString(
1214            parameterMap, PortletDataHandlerKeys.USER_ID_STRATEGY);
1215
1216        StopWatch stopWatch = null;
1217
1218        if (_log.isInfoEnabled()) {
1219            stopWatch = new StopWatch();
1220
1221            stopWatch.start();
1222        }
1223
1224        Layout layout = LayoutLocalServiceUtil.getLayout(plid);
1225
1226        long companyId = layout.getCompanyId();
1227
1228        User user = userPersistence.findByPrimaryKey(userId);
1229
1230        // User ID strategy
1231
1232        UserIdStrategy strategy = null;
1233
1234        if (UserIdStrategy.ALWAYS_CURRENT_USER_ID.equals(userIdStrategy)) {
1235            strategy = new AlwaysCurrentUserIdStrategy(user);
1236        }
1237        else if (UserIdStrategy.CURRENT_USER_ID.equals(userIdStrategy)) {
1238            strategy = new CurrentUserIdStrategy(user);
1239        }
1240
1241        ZipReader zipReader = new ZipReader(is);
1242
1243        PortletDataContext context = new PortletDataContextImpl(
1244            companyId, layout.getGroupId(), parameterMap,
1245            CollectionFactory.getHashSet(), strategy, zipReader);
1246
1247        context.setPlid(plid);
1248
1249        // Zip
1250
1251        Element root = null;
1252
1253        try {
1254
1255            // XML
1256
1257            String xml = zipReader.getEntryAsString("portlet.xml");
1258
1259            SAXReader reader = new SAXReader();
1260
1261            Document doc = reader.read(new StringReader(xml));
1262
1263            root = doc.getRootElement();
1264        }
1265        catch (Exception e) {
1266            throw new SystemException(e);
1267        }
1268
1269        // Build compatibility
1270
1271        Element header = (Element)root.element("header");
1272
1273        int buildNumber = ReleaseInfo.getBuildNumber();
1274
1275        int importBuildNumber = GetterUtil.getInteger(
1276            header.attributeValue("build-number"));
1277
1278        if (buildNumber != importBuildNumber) {
1279            throw new LayoutImportException(
1280                "LAR build number " + importBuildNumber + " does not match " +
1281                    "portal build number " + buildNumber);
1282        }
1283
1284        String type = header.attributeValue("type");
1285
1286        if (!type.equals("portlet")) {
1287            throw new LayoutImportException(
1288                "Invalid type of LAR file (" + type + ")");
1289        }
1290
1291        // Read comments, ratings, and tags to make them available to the data
1292        // handlers through the context
1293
1294        readComments(context, root);
1295        readRatings(context, root);
1296        readTags(context, root);
1297
1298        // Delete portlet data
1299
1300        if (_log.isDebugEnabled()) {
1301            _log.debug("Deleting portlet data");
1302        }
1303
1304        if (deletePortletData) {
1305            deletePortletData(context, layout, root);
1306        }
1307
1308        // Portlet preferences
1309
1310        importPortletPreferences(
1311            layout.getCompanyId(), plid, root, importPortletSetup,
1312            importUserPreferences);
1313
1314        // Portlet data
1315
1316        if (_log.isDebugEnabled()) {
1317            _log.debug("Importing portlet data");
1318        }
1319
1320        if (importPortletData) {
1321            importPortletData(context, layout, root);
1322        }
1323
1324        if (_log.isInfoEnabled()) {
1325            _log.info(
1326                "Importing portlet data takes " + stopWatch.getTime() + " ms");
1327        }
1328    }
1329
1330    public void setLayouts(
1331            long groupId, boolean privateLayout, long parentLayoutId,
1332            long[] layoutIds)
1333        throws PortalException, SystemException {
1334
1335        if (layoutIds == null) {
1336            return;
1337        }
1338
1339        if (parentLayoutId == LayoutImpl.DEFAULT_PARENT_LAYOUT_ID) {
1340            if (layoutIds.length < 1) {
1341                throw new RequiredLayoutException(
1342                    RequiredLayoutException.AT_LEAST_ONE);
1343            }
1344
1345            Layout layout = layoutPersistence.findByG_P_L(
1346                groupId, privateLayout, layoutIds[0]);
1347
1348            if (!layout.getType().equals(LayoutImpl.TYPE_PORTLET)) {
1349                throw new RequiredLayoutException(
1350                    RequiredLayoutException.FIRST_LAYOUT_TYPE);
1351            }
1352
1353            if (layout.isHidden()) {
1354                throw new RequiredLayoutException(
1355                    RequiredLayoutException.FIRST_LAYOUT_HIDDEN);
1356            }
1357        }
1358
1359        Set layoutIdsSet = new LinkedHashSet();
1360
1361        for (int i = 0; i < layoutIds.length; i++) {
1362            layoutIdsSet.add(new Long(layoutIds[i]));
1363        }
1364
1365        Set newLayoutIdsSet = CollectionFactory.getHashSet();
1366
1367        Iterator itr = layoutPersistence.findByG_P_P(
1368            groupId, privateLayout, parentLayoutId).iterator();
1369
1370        while (itr.hasNext()) {
1371            Layout layout = (Layout)itr.next();
1372
1373            Long layoutIdObj = new Long(layout.getLayoutId());
1374
1375            if (!layoutIdsSet.contains(layoutIdObj)) {
1376                deleteLayout(layout, true);
1377            }
1378            else {
1379                newLayoutIdsSet.add(layoutIdObj);
1380            }
1381        }
1382
1383        int priority = 0;
1384
1385        itr = layoutIdsSet.iterator();
1386
1387        while (itr.hasNext()) {
1388            Long layoutIdObj = (Long)itr.next();
1389
1390            Layout layout = layoutPersistence.findByG_P_L(
1391                groupId, privateLayout, layoutIdObj.longValue());
1392
1393            layout.setPriority(priority++);
1394
1395            layoutPersistence.update(layout);
1396        }
1397
1398        layoutSetLocalService.updatePageCount(groupId, privateLayout);
1399    }
1400
1401    public Layout updateLayout(
1402            long groupId, boolean privateLayout, long layoutId,
1403            long parentLayoutId, Map localeNamesMap, Map localeTitlesMap,
1404            String description, String type, boolean hidden, String friendlyURL)
1405        throws PortalException, SystemException {
1406
1407        return updateLayout(
1408            groupId, privateLayout, layoutId, parentLayoutId, localeNamesMap,
1409            localeTitlesMap, description, type, hidden, friendlyURL, null,
1410            null);
1411    }
1412
1413    public Layout updateLayout(
1414            long groupId, boolean privateLayout, long layoutId,
1415            long parentLayoutId, Map localeNamesMap, Map localeTitlesMap,
1416            String description, String type, boolean hidden, String friendlyURL,
1417            Boolean iconImage, byte[] iconBytes)
1418        throws PortalException, SystemException {
1419
1420        // Layout
1421
1422        parentLayoutId = getParentLayoutId(
1423            groupId, privateLayout, parentLayoutId);
1424        friendlyURL = getFriendlyURL(friendlyURL);
1425
1426        validate(
1427            groupId, privateLayout, layoutId, parentLayoutId, type, hidden,
1428            friendlyURL);
1429
1430        validateParentLayoutId(
1431            groupId, privateLayout, layoutId, parentLayoutId);
1432
1433        Layout layout = layoutPersistence.findByG_P_L(
1434            groupId, privateLayout, layoutId);
1435
1436        if (parentLayoutId != layout.getParentLayoutId()) {
1437            layout.setPriority(
1438                getNextPriority(groupId, privateLayout, parentLayoutId));
1439        }
1440
1441        layout.setParentLayoutId(parentLayoutId);
1442        layout.setDescription(description);
1443        layout.setType(type);
1444        layout.setHidden(hidden);
1445        layout.setFriendlyURL(friendlyURL);
1446
1447        setLocalizedAttributes(layout, localeNamesMap, localeTitlesMap);
1448
1449        if (iconImage != null) {
1450            layout.setIconImage(iconImage.booleanValue());
1451
1452            if (iconImage.booleanValue()) {
1453                long iconImageId = layout.getIconImageId();
1454
1455                if (iconImageId <= 0) {
1456                    iconImageId = counterLocalService.increment();
1457
1458                    layout.setIconImageId(iconImageId);
1459                }
1460            }
1461        }
1462
1463        layoutPersistence.update(layout);
1464
1465        // Icon
1466
1467        if (iconImage != null) {
1468            if (!iconImage.booleanValue()) {
1469                ImageLocalUtil.deleteImage(layout.getIconImageId());
1470            }
1471            else if ((iconBytes != null) && (iconBytes.length > 0)) {
1472                ImageLocalUtil.updateImage(layout.getIconImageId(), iconBytes);
1473            }
1474        }
1475
1476        try {
1477            if (layout.getDlFolderId() > 0) {
1478                DLFolder folder = dlFolderLocalService.getFolder(
1479                    layout.getDlFolderId());
1480
1481                dlFolderLocalService.updateFolder(
1482                    folder.getFolderId(), folder.getParentFolderId(),
1483                    layout.getName(), folder.getDescription());
1484            }
1485        }
1486        catch (NoSuchFolderException nsfe) {
1487        }
1488
1489        return layout;
1490    }
1491
1492    public Layout updateLayout(
1493            long groupId, boolean privateLayout, long layoutId,
1494            String typeSettings)
1495        throws PortalException, SystemException {
1496
1497        Layout layout = layoutPersistence.findByG_P_L(
1498            groupId, privateLayout, layoutId);
1499
1500        layout.setTypeSettings(typeSettings);
1501
1502        layoutPersistence.update(layout);
1503
1504        return layout;
1505    }
1506
1507    public Layout updateLookAndFeel(
1508            long groupId, boolean privateLayout, long layoutId, String themeId,
1509            String colorSchemeId, String css, boolean wapTheme)
1510        throws PortalException, SystemException {
1511
1512        Layout layout = layoutPersistence.findByG_P_L(
1513            groupId, privateLayout, layoutId);
1514
1515        if (wapTheme) {
1516            layout.setWapThemeId(themeId);
1517            layout.setWapColorSchemeId(colorSchemeId);
1518        }
1519        else {
1520            layout.setThemeId(themeId);
1521            layout.setColorSchemeId(colorSchemeId);
1522            layout.setCss(css);
1523        }
1524
1525        layoutPersistence.update(layout);
1526
1527        return layout;
1528    }
1529
1530    public Layout updateName(long plid, String name, String languageId)
1531        throws PortalException, SystemException {
1532
1533        Layout layout = layoutPersistence.findByPrimaryKey(plid);
1534
1535        return updateName(layout, name, languageId);
1536    }
1537
1538    public Layout updateName(
1539            long groupId, boolean privateLayout, long layoutId, String name,
1540            String languageId)
1541        throws PortalException, SystemException {
1542
1543        Layout layout = layoutPersistence.findByG_P_L(
1544            groupId, privateLayout, layoutId);
1545
1546        return updateName(layout, name, languageId);
1547    }
1548
1549    public Layout updateName(Layout layout, String name, String languageId)
1550        throws PortalException, SystemException {
1551
1552        layout.setName(name, LocaleUtil.fromLanguageId(languageId));
1553
1554        layoutPersistence.update(layout);
1555
1556        try {
1557            if (layout.getDlFolderId() > 0) {
1558                DLFolder folder = dlFolderLocalService.getFolder(
1559                    layout.getDlFolderId());
1560
1561                dlFolderLocalService.updateFolder(
1562                    folder.getFolderId(), folder.getParentFolderId(), name,
1563                    folder.getDescription());
1564            }
1565        }
1566        catch (NoSuchFolderException nsfe) {
1567        }
1568
1569        return layout;
1570    }
1571
1572    public Layout updateParentLayoutId(long plid, long parentPlid)
1573        throws PortalException, SystemException {
1574
1575        Layout layout = layoutPersistence.findByPrimaryKey(plid);
1576
1577        long parentLayoutId = LayoutImpl.DEFAULT_PARENT_LAYOUT_ID;
1578
1579        if (parentPlid > 0) {
1580            try {
1581                Layout parentLayout = layoutPersistence.findByPrimaryKey(
1582                    parentPlid);
1583
1584                parentLayoutId = parentLayout.getLayoutId();
1585            }
1586            catch (NoSuchLayoutException nsle) {
1587            }
1588        }
1589
1590        parentLayoutId = getParentLayoutId(
1591            layout.getGroupId(), layout.isPrivateLayout(), parentLayoutId);
1592
1593        validateParentLayoutId(
1594            layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(),
1595            parentLayoutId);
1596
1597        if (parentLayoutId != layout.getParentLayoutId()) {
1598            int priority = getNextPriority(
1599                layout.getGroupId(), layout.isPrivateLayout(), parentLayoutId);
1600
1601            layout.setPriority(priority);
1602        }
1603
1604        layout.setParentLayoutId(parentLayoutId);
1605
1606        layoutPersistence.update(layout);
1607
1608        return layout;
1609    }
1610
1611    public Layout updateParentLayoutId(
1612            long groupId, boolean privateLayout, long layoutId,
1613            long parentLayoutId)
1614        throws PortalException, SystemException {
1615
1616        parentLayoutId = getParentLayoutId(
1617            groupId, privateLayout, parentLayoutId);
1618
1619        validateParentLayoutId(
1620            groupId, privateLayout, layoutId, parentLayoutId);
1621
1622        Layout layout = layoutPersistence.findByG_P_L(
1623            groupId, privateLayout, layoutId);
1624
1625        if (parentLayoutId != layout.getParentLayoutId()) {
1626            layout.setPriority(
1627                getNextPriority(groupId, privateLayout, parentLayoutId));
1628        }
1629
1630        layout.setParentLayoutId(parentLayoutId);
1631
1632        layoutPersistence.update(layout);
1633
1634        return layout;
1635    }
1636
1637    public Layout updatePriority(long plid, int priority)
1638        throws PortalException, SystemException {
1639
1640        Layout layout = layoutPersistence.findByPrimaryKey(plid);
1641
1642        return updatePriority(layout, priority);
1643    }
1644
1645    public Layout updatePriority(
1646            long groupId, boolean privateLayout, long layoutId, int priority)
1647        throws PortalException, SystemException {
1648
1649        Layout layout = layoutPersistence.findByG_P_L(
1650            groupId, privateLayout, layoutId);
1651
1652        return updatePriority(layout, priority);
1653    }
1654
1655    public Layout updatePriority(Layout layout, int priority)
1656        throws PortalException, SystemException {
1657
1658        if (layout.getPriority() == priority) {
1659            return layout;
1660        }
1661
1662        boolean lessThan = false;
1663
1664        if (layout.getPriority() < priority) {
1665            lessThan = true;
1666        }
1667
1668        layout.setPriority(priority);
1669
1670        layoutPersistence.update(layout);
1671
1672        priority = 0;
1673
1674        List layouts = layoutPersistence.findByG_P_P(
1675            layout.getGroupId(), layout.isPrivateLayout(),
1676            layout.getParentLayoutId());
1677
1678        Collections.sort(
1679            layouts, new LayoutPriorityComparator(layout, lessThan));
1680
1681        Iterator itr = layouts.iterator();
1682
1683        while (itr.hasNext()) {
1684            Layout curLayout = (Layout)itr.next();
1685
1686            curLayout.setPriority(priority++);
1687
1688            layoutPersistence.update(curLayout);
1689
1690            if (curLayout.equals(layout)) {
1691                layout = curLayout;
1692            }
1693        }
1694
1695        return layout;
1696    }
1697
1698    protected void deleteMissingLayouts(
1699            long groupId, boolean privateLayout, Set newLayoutIds)
1700        throws PortalException, SystemException {
1701
1702        // Layouts
1703
1704        if (_log.isDebugEnabled()) {
1705            if (newLayoutIds.size() > 0) {
1706                _log.debug("Delete missing layouts");
1707            }
1708        }
1709
1710        List layouts = layoutPersistence.findByG_P(groupId, privateLayout);
1711
1712        Iterator itr = layouts.iterator();
1713
1714        while (itr.hasNext()) {
1715            Layout layout = (Layout)itr.next();
1716
1717            if (!newLayoutIds.contains(new Long(layout.getLayoutId()))) {
1718                try {
1719                    deleteLayout(layout, false);
1720                }
1721                catch (NoSuchLayoutException nsle) {
1722                }
1723            }
1724        }
1725
1726        // Layout set
1727
1728        layoutSetLocalService.updatePageCount(groupId, privateLayout);
1729    }
1730
1731    protected void deletePortletData(
1732            PortletDataContext context, Layout layout, Element parentEl)
1733        throws PortalException, SystemException {
1734
1735        Iterator itr = parentEl.elements("portlet-data").iterator();
1736
1737        while (itr.hasNext()) {
1738            Element el = (Element)itr.next();
1739
1740            String portletId = el.attributeValue("portlet-id");
1741
1742            try {
1743                PortletPreferences portletPreferences =
1744                    portletPreferencesPersistence.findByO_O_P_P(
1745                        PortletKeys.PREFS_OWNER_ID_DEFAULT,
1746                        PortletKeys.PREFS_OWNER_TYPE_LAYOUT, layout.getPlid(),
1747                        portletId);
1748
1749                String preferences = deletePortletData(
1750                    context, portletId, portletPreferences, el);
1751
1752                if (preferences != null) {
1753                    portletPreferences.setPreferences(preferences);
1754
1755                    portletPreferencesPersistence.update(portletPreferences);
1756                }
1757            }
1758            catch (NoSuchPortletPreferencesException nsppe) {
1759            }
1760        }
1761    }
1762
1763    protected String deletePortletData(
1764            PortletDataContext context, String portletId,
1765            PortletPreferences portletPreferences, Element parentEl)
1766        throws PortalException, SystemException {
1767
1768        Portlet portlet = portletLocalService.getPortletById(
1769            context.getCompanyId(), portletId);
1770
1771        if (portlet == null) {
1772            if (_log.isDebugEnabled()) {
1773                _log.debug(
1774                    "Do not delete portlet data for " + portletId +
1775                        " because the portlet does not exist");
1776            }
1777
1778            return null;
1779        }
1780
1781        PortletDataHandler portletDataHandler =
1782            portlet.getPortletDataHandlerInstance();
1783
1784        if (portletDataHandler == null) {
1785            if (_log.isDebugEnabled()) {
1786                _log.debug(
1787                    "Do not delete portlet data for " + portletId +
1788                        " because the portlet does not have a " +
1789                            "PortletDataHandler");
1790            }
1791
1792            return null;
1793        }
1794
1795        if (_log.isDebugEnabled()) {
1796            _log.debug("Deleting data for " + portletId);
1797        }
1798
1799        PortletPreferencesImpl prefsImpl =
1800            (PortletPreferencesImpl)PortletPreferencesSerializer.fromDefaultXML(
1801                portletPreferences.getPreferences());
1802
1803        prefsImpl = (PortletPreferencesImpl)portletDataHandler.deleteData(
1804            context, portletId, prefsImpl);
1805
1806        if (prefsImpl == null) {
1807            return null;
1808        }
1809
1810        return PortletPreferencesSerializer.toXML(prefsImpl);
1811    }
1812
1813    protected void exportComments(PortletDataContext context, Element root)
1814        throws SystemException {
1815
1816        try {
1817            XStream xStream = new XStream();
1818
1819            Map commentsMap = context.getComments();
1820
1821            Iterator itr = commentsMap.keySet().iterator();
1822
1823            while (itr.hasNext()) {
1824                String key = (String)itr.next();
1825
1826                String[] comment = key.split(StringPool.POUND);
1827
1828                Element el = root.addElement("comments");
1829
1830                el.addAttribute("class-name", comment[0]);
1831                el.addAttribute("class-pk", comment[1]);
1832
1833                List messages = (List)commentsMap.get(key);
1834
1835                String xml = xStream.toXML(messages);
1836
1837                Document tempDoc = PortalUtil.readDocumentFromXML(xml);
1838
1839                el.content().add(tempDoc.getRootElement().createCopy());
1840            }
1841        }
1842        catch (Exception e) {
1843            throw new SystemException(e);
1844        }
1845    }
1846
1847    protected Element exportGroupPermissions(
1848            long companyId, long groupId, String resourceName,
1849            String resourcePrimKey, Element parentEl, String elName)
1850        throws PortalException, SystemException {
1851
1852        Element el = parentEl.addElement(elName);
1853
1854        List permissions = permissionLocalService.getGroupPermissions(
1855            groupId, companyId, resourceName, ResourceImpl.SCOPE_INDIVIDUAL,
1856            resourcePrimKey);
1857
1858        List actions = ResourceActionsUtil.getActions(permissions);
1859
1860        for (int i = 0; i < actions.size(); i++) {
1861            String action = (String)actions.get(i);
1862
1863            Element actionKeyEl = el.addElement("action-key");
1864
1865            actionKeyEl.addText(action);
1866        }
1867
1868        return el;
1869    }
1870
1871    protected void exportGroupRoles(
1872            LayoutCache layoutCache, long companyId, long groupId,
1873            String resourceName, String entityName, Element parentEl)
1874        throws PortalException, SystemException {
1875
1876        List roles = layoutCache.getGroupRoles(groupId);
1877
1878        Element groupEl = exportRoles(
1879            companyId, resourceName, ResourceImpl.SCOPE_GROUP,
1880            String.valueOf(groupId), parentEl, entityName + "-roles", roles);
1881
1882        if (groupEl.elements().isEmpty()) {
1883            parentEl.remove(groupEl);
1884        }
1885    }
1886
1887    protected void exportInheritedPermissions(
1888            LayoutCache layoutCache, long companyId, String resourceName,
1889            String resourcePrimKey, Element parentEl, String entityName)
1890        throws PortalException, SystemException {
1891
1892        Element entityPermissionsEl = DocumentHelper.createElement(
1893            entityName + "-permissions");
1894
1895        Map entityMap = layoutCache.getEntityMap(companyId, entityName);
1896
1897        Iterator itr = entityMap.entrySet().iterator();
1898
1899        while (itr.hasNext()) {
1900            Map.Entry entry = (Map.Entry)itr.next();
1901
1902            String name = entry.getKey().toString();
1903
1904            long entityGroupId = ((Long)entry.getValue()).longValue();
1905
1906            Element entityEl = exportGroupPermissions(
1907                companyId, entityGroupId, resourceName, resourcePrimKey,
1908                entityPermissionsEl, entityName + "-actions");
1909
1910            if (entityEl.elements().isEmpty()) {
1911                entityPermissionsEl.remove(entityEl);
1912            }
1913            else {
1914                entityEl.addAttribute("name", name);
1915            }
1916        }
1917
1918        if (!entityPermissionsEl.elements().isEmpty()) {
1919            parentEl.add(entityPermissionsEl);
1920        }
1921    }
1922
1923    protected void exportInheritedRoles(
1924            LayoutCache layoutCache, long companyId, long groupId,
1925            String resourceName, String entityName, Element parentEl)
1926        throws PortalException, SystemException {
1927
1928        Element entityRolesEl = DocumentHelper.createElement(
1929            entityName + "-roles");
1930
1931        Map entityMap = layoutCache.getEntityMap(companyId, entityName);
1932
1933        Iterator itr = entityMap.entrySet().iterator();
1934
1935        while (itr.hasNext()) {
1936            Map.Entry entry = (Map.Entry)itr.next();
1937
1938            String name = entry.getKey().toString();
1939
1940            long entityGroupId = ((Long)entry.getValue()).longValue();
1941
1942            List entityRoles = layoutCache.getGroupRoles(entityGroupId);
1943
1944            Element entityEl = exportRoles(
1945                companyId, resourceName, ResourceImpl.SCOPE_GROUP,
1946                String.valueOf(groupId), entityRolesEl, entityName,
1947                entityRoles);
1948
1949            if (entityEl.elements().isEmpty()) {
1950                entityRolesEl.remove(entityEl);
1951            }
1952            else {
1953                entityEl.addAttribute("name", name);
1954            }
1955        }
1956
1957        if (!entityRolesEl.elements().isEmpty()) {
1958            parentEl.add(entityRolesEl);
1959        }
1960    }
1961
1962    protected void exportLayoutPermissions(
1963            LayoutCache layoutCache, long companyId, long groupId,
1964            Group guestGroup, Layout layout, Element permissionsEl,
1965            boolean exportUserPermissions)
1966        throws PortalException, SystemException {
1967
1968        String resourceName = Layout.class.getName();
1969        String resourcePrimKey = String.valueOf(layout.getPlid());
1970
1971        exportGroupPermissions(
1972            companyId, groupId, resourceName, resourcePrimKey, permissionsEl,
1973            "community-actions");
1974
1975        if (groupId != guestGroup.getGroupId()) {
1976            exportGroupPermissions(
1977                companyId, guestGroup.getGroupId(), resourceName,
1978                resourcePrimKey, permissionsEl, "guest-actions");
1979        }
1980
1981        if (exportUserPermissions) {
1982            exportUserPermissions(
1983                layoutCache, companyId, groupId, resourceName, resourcePrimKey,
1984                permissionsEl);
1985        }
1986
1987        exportInheritedPermissions(
1988            layoutCache, companyId, resourceName, resourcePrimKey,
1989            permissionsEl, "organization");
1990
1991        exportInheritedPermissions(
1992            layoutCache, companyId, resourceName, resourcePrimKey,
1993            permissionsEl, "location");
1994
1995        exportInheritedPermissions(
1996            layoutCache, companyId, resourceName, resourcePrimKey,
1997            permissionsEl, "user-group");
1998    }
1999
2000    protected void exportLayoutRoles(
2001            LayoutCache layoutCache, long companyId, long groupId,
2002            Element rolesEl)
2003        throws PortalException, SystemException {
2004
2005        String resourceName = Layout.class.getName();
2006
2007        exportGroupRoles(
2008            layoutCache, companyId, groupId, resourceName, "community",
2009            rolesEl);
2010
2011        exportUserRoles(layoutCache, companyId, groupId, resourceName, rolesEl);
2012
2013        exportInheritedRoles(
2014            layoutCache, companyId, groupId, resourceName, "organization",
2015            rolesEl);
2016
2017        exportInheritedRoles(
2018            layoutCache, companyId, groupId, resourceName, "location", rolesEl);
2019
2020        exportInheritedRoles(
2021            layoutCache, companyId, groupId, resourceName, "user-group",
2022            rolesEl);
2023    }
2024
2025    protected void exportPortletData(
2026            PortletDataContext context, Layout layout,
2027            LayoutTypePortlet layoutTypePortlet, Element parentEl)
2028        throws PortalException, SystemException {
2029
2030        Iterator itr = portletPreferencesLocalService.getPortletPreferences(
2031            layout.getPlid()).iterator();
2032
2033        while (itr.hasNext()) {
2034            PortletPreferences portletPreferences =
2035                (PortletPreferences)itr.next();
2036
2037            javax.portlet.PortletPreferences jxPrefs =
2038                portletPreferencesLocalService.getPreferences(
2039                    layout.getCompanyId(), portletPreferences.getOwnerId(),
2040                    portletPreferences.getOwnerType(),
2041                    portletPreferences.getPlid(),
2042                    portletPreferences.getPortletId());
2043
2044            String portletId = portletPreferences.getPortletId();
2045
2046            if (layoutTypePortlet.hasPortletId(portletId)) {
2047                exportPortletData(context, portletId, jxPrefs, parentEl);
2048            }
2049        }
2050    }
2051
2052    protected void exportPortletData(
2053            PortletDataContext context, String portletId,
2054            javax.portlet.PortletPreferences portletPreferences,
2055            Element parentEl)
2056        throws PortalException, SystemException {
2057
2058        Portlet portlet = portletLocalService.getPortletById(
2059            context.getCompanyId(), portletId);
2060
2061        if (portlet == null) {
2062            if (_log.isDebugEnabled()) {
2063                _log.debug(
2064                    "Do not export portlet data for " + portletId +
2065                        " because the portlet does not exist");
2066            }
2067
2068            return;
2069        }
2070
2071        PortletDataHandler portletDataHandler =
2072            portlet.getPortletDataHandlerInstance();
2073
2074        if (portletDataHandler == null) {
2075            return;
2076        }
2077
2078        if (_log.isDebugEnabled()) {
2079            _log.debug("Exporting data for " + portletId);
2080        }
2081
2082        Map parameterMap = context.getParameterMap();
2083
2084        boolean exportData = false;
2085
2086        if (MapUtil.getBoolean(
2087                parameterMap,
2088                PortletDataHandlerKeys.PORTLET_DATA + "_" + portletId) ||
2089            MapUtil.getBoolean(
2090                parameterMap, PortletDataHandlerKeys.PORTLET_DATA_ALL)) {
2091
2092            exportData = true;
2093        }
2094
2095        if (!exportData) {
2096            if (_log.isDebugEnabled()) {
2097                _log.debug(
2098                    "Not exporting data for " + portletId +
2099                        " because it was not selected by the user");
2100            }
2101
2102            return;
2103        }
2104
2105        String data = portletDataHandler.exportData(
2106            context, portletId, portletPreferences);
2107
2108        if (data == null) {
2109            if (_log.isDebugEnabled()) {
2110                _log.debug(
2111                    "Not exporting data for " + portletId +
2112                        " because null data was returned");
2113            }
2114
2115            return;
2116        }
2117
2118        Element el = parentEl.addElement("portlet-data");
2119
2120        el.addAttribute("portlet-id", portletId);
2121        el.addCDATA(data);
2122    }
2123
2124    protected void exportPortletPermissions(
2125            LayoutCache layoutCache, long companyId, long groupId,
2126            Group guestGroup, Layout layout,
2127            LayoutTypePortlet layoutTypePortlet, Set portletIds,
2128            Element permissionsEl, boolean exportUserPermissions)
2129        throws PortalException, SystemException {
2130
2131        Iterator itr = layoutTypePortlet.getPortletIds().iterator();
2132
2133        while (itr.hasNext()) {
2134            String portletId = (String)itr.next();
2135
2136            if (!portletIds.contains(portletId)) {
2137                portletIds.add(portletId);
2138            }
2139
2140            if (layoutTypePortlet.hasPortletId(portletId)) {
2141                String resourceName = PortletImpl.getRootPortletId(portletId);
2142                String resourcePrimKey = PortletPermissionUtil.getPrimaryKey(
2143                    layout.getPlid(), portletId);
2144
2145                Element portletEl = permissionsEl.addElement("portlet");
2146
2147                portletEl.addAttribute("portlet-id", portletId);
2148
2149                exportGroupPermissions(
2150                    companyId, groupId, resourceName, resourcePrimKey,
2151                    portletEl, "community-actions");
2152
2153                if (groupId != guestGroup.getGroupId()) {
2154                    exportGroupPermissions(
2155                        companyId, guestGroup.getGroupId(), resourceName,
2156                        resourcePrimKey, portletEl, "guest-actions");
2157                }
2158
2159                if (exportUserPermissions) {
2160                    exportUserPermissions(
2161                        layoutCache, companyId, groupId, resourceName,
2162                        resourcePrimKey, portletEl);
2163                }
2164
2165                exportInheritedPermissions(
2166                    layoutCache, companyId, resourceName, resourcePrimKey,
2167                    portletEl, "organization");
2168
2169                exportInheritedPermissions(
2170                    layoutCache, companyId, resourceName, resourcePrimKey,
2171                    portletEl, "location");
2172
2173                exportInheritedPermissions(
2174                    layoutCache, companyId, resourceName, resourcePrimKey,
2175                    portletEl, "user-group");
2176            }
2177        }
2178    }
2179
2180    protected void exportPortletPreferences(
2181            long ownerId, int ownerType, long plid, boolean defaultUser,
2182            Element parentEl)
2183        throws PortalException, SystemException {
2184
2185        exportPortletPreferences(
2186            ownerId, ownerType, defaultUser, plid, null, parentEl);
2187    }
2188
2189    protected void exportPortletPreferences(
2190            long ownerId, int ownerType, boolean defaultUser, long plid,
2191            LayoutTypePortlet layoutTypePortlet, Element parentEl)
2192        throws PortalException, SystemException {
2193
2194        Iterator itr = portletPreferencesLocalService.getPortletPreferences(
2195            ownerId, ownerType, plid).iterator();
2196
2197        while (itr.hasNext()) {
2198            PortletPreferences portletPreferences =
2199                (PortletPreferences)itr.next();
2200
2201            String portletId = portletPreferences.getPortletId();
2202
2203            if ((layoutTypePortlet == null) ||
2204                (layoutTypePortlet.hasPortletId(portletId))) {
2205
2206                Element el = parentEl.addElement("portlet-preferences");
2207
2208                el.addAttribute("owner-id", String.valueOf(ownerId));
2209                el.addAttribute("owner-type", String.valueOf(ownerType));
2210                el.addAttribute("default-user", String.valueOf(defaultUser));
2211                el.addAttribute("plid", String.valueOf(plid));
2212                el.addAttribute("portlet-id", portletId);
2213                el.addElement("preferences").addCDATA(
2214                    portletPreferences.getPreferences());
2215            }
2216        }
2217    }
2218
2219    protected void exportPortletPreferences(
2220            long ownerId, int ownerType, boolean defaultUser, Layout layout,
2221            String portletId, Element parentEl)
2222        throws PortalException, SystemException {
2223
2224        PortletPreferences portletPreferences = null;
2225
2226        long plid = layout.getPlid();
2227
2228        if ((ownerType == PortletKeys.PREFS_OWNER_TYPE_COMPANY) ||
2229            (ownerType == PortletKeys.PREFS_OWNER_TYPE_GROUP)) {
2230
2231            plid = PortletKeys.PREFS_OWNER_ID_DEFAULT;
2232        }
2233
2234        try {
2235            portletPreferences =
2236                portletPreferencesLocalService.getPortletPreferences(
2237                    ownerId, ownerType, plid, portletId);
2238
2239            LayoutTypePortlet layoutTypePortlet =
2240                (LayoutTypePortlet)layout.getLayoutType();
2241
2242            if ((layoutTypePortlet == null) ||
2243                (layoutTypePortlet.hasPortletId(portletId))) {
2244
2245                Element el = parentEl.addElement("portlet-preferences");
2246
2247                el.addAttribute("owner-id", String.valueOf(ownerId));
2248                el.addAttribute("owner-type", String.valueOf(ownerType));
2249                el.addAttribute("default-user", String.valueOf(defaultUser));
2250                el.addAttribute("plid", String.valueOf(plid));
2251                el.addAttribute("portlet-id", portletId);
2252                el.addElement("preferences").addCDATA(
2253                    portletPreferences.getPreferences());
2254            }
2255        }
2256        catch (NoSuchPortletPreferencesException nsppe) {
2257        }
2258    }
2259
2260    protected void exportPortletRoles(
2261            LayoutCache layoutCache, long companyId, long groupId,
2262            Set portletIds, Element rolesEl)
2263        throws PortalException, SystemException {
2264
2265        Iterator itr = portletIds.iterator();
2266
2267        while (itr.hasNext()) {
2268            String portletId = (String)itr.next();
2269
2270            String resourceName = PortletImpl.getRootPortletId(portletId);
2271
2272            Element portletEl = rolesEl.addElement("portlet");
2273
2274            portletEl.addAttribute("portlet-id", portletId);
2275
2276            exportGroupRoles(
2277                layoutCache, companyId, groupId, resourceName, "community",
2278                portletEl);
2279
2280            exportUserRoles(
2281                layoutCache, companyId, groupId, resourceName, portletEl);
2282
2283            exportInheritedRoles(
2284                layoutCache, companyId, groupId, resourceName, "organization",
2285                portletEl);
2286
2287            exportInheritedRoles(
2288                layoutCache, companyId, groupId, resourceName, "location",
2289                portletEl);
2290
2291            exportInheritedRoles(
2292                layoutCache, companyId, groupId, resourceName, "user-group",
2293                portletEl);
2294
2295            if (portletEl.elements().isEmpty()) {
2296                rolesEl.remove(portletEl);
2297            }
2298        }
2299    }
2300
2301    protected Element exportRoles(
2302            long companyId, String resourceName, int scope,
2303            String resourcePrimKey, Element parentEl, String elName,
2304            List roles)
2305        throws PortalException, SystemException {
2306
2307        Element el = parentEl.addElement(elName);
2308
2309        Map resourceRoles = roleLocalService.getResourceRoles(
2310            companyId, resourceName, scope, resourcePrimKey);
2311
2312        Iterator itr = resourceRoles.entrySet().iterator();
2313
2314        while (itr.hasNext()) {
2315            Map.Entry entry = (Map.Entry)itr.next();
2316
2317            String roleName = entry.getKey().toString();
2318
2319            if (hasRole(roles, roleName)) {
2320                Element roleEl = el.addElement("role");
2321
2322                roleEl.addAttribute("name", roleName);
2323
2324                List actions = (List)entry.getValue();
2325
2326                for (int i = 0; i < actions.size(); i++) {
2327                    String action = (String)actions.get(i);
2328
2329                    Element actionKeyEl = roleEl.addElement("action-key");
2330
2331                    actionKeyEl.addText(action);
2332                    actionKeyEl.addAttribute("scope", String.valueOf(scope));
2333                }
2334            }
2335        }
2336
2337        return el;
2338    }
2339
2340    protected void exportRatings(PortletDataContext context, Element root)
2341        throws SystemException {
2342
2343        try {
2344            XStream xStream = new XStream();
2345
2346            Map ratingsEntriesMap = context.getRatingsEntries();
2347
2348            Iterator itr = ratingsEntriesMap.keySet().iterator();
2349
2350            while (itr.hasNext()) {
2351                String key = (String)itr.next();
2352
2353                String[] ratingsEntry = key.split(StringPool.POUND);
2354
2355                Element el = root.addElement("ratings");
2356
2357                el.addAttribute("class-name", ratingsEntry[0]);
2358                el.addAttribute("class-pk", ratingsEntry[1]);
2359
2360                List ratingsEntries = (List)ratingsEntriesMap.get(key);
2361
2362                String xml = xStream.toXML(ratingsEntries);
2363
2364                Document tempDoc = PortalUtil.readDocumentFromXML(xml);
2365
2366                el.content().add(tempDoc.getRootElement().createCopy());
2367            }
2368        }
2369        catch (Exception e) {
2370            throw new SystemException(e);
2371        }
2372    }
2373
2374    protected void exportTags(PortletDataContext context, Element root) {
2375        Map tagsEntries = context.getTagsEntries();
2376
2377        Iterator itr = tagsEntries.keySet().iterator();
2378
2379        while (itr.hasNext()) {
2380            String key = (String)itr.next();
2381
2382            String[] tagsEntry = key.split(StringPool.POUND);
2383
2384            Element el = root.addElement("tags");
2385
2386            el.addAttribute("class-name", tagsEntry[0]);
2387            el.addAttribute("class-pk", tagsEntry[1]);
2388            el.addAttribute(
2389                "entries",
2390                StringUtil.merge((String[])tagsEntries.get(key), ","));
2391        }
2392    }
2393
2394    protected byte[] exportTheme(LayoutSet layoutSet)
2395        throws IOException, PortalException, SystemException {
2396
2397        Theme theme = layoutSet.getTheme();
2398
2399        ZipWriter zipWriter = new ZipWriter();
2400
2401        String lookAndFeelXML = ContentUtil.get(
2402            "com/liferay/portal/dependencies/liferay-look-and-feel.xml.tmpl");
2403
2404        lookAndFeelXML = StringUtil.replace(
2405            lookAndFeelXML,
2406            new String[] {
2407                "[$TEMPLATE_EXTENSION$]", "[$VIRTUAL_PATH$]"
2408            },
2409            new String[] {
2410                theme.getTemplateExtension(), theme.getVirtualPath()
2411            }
2412        );
2413
2414        zipWriter.addEntry("liferay-look-and-feel.xml", lookAndFeelXML);
2415
2416        String servletContextName = theme.getServletContextName();
2417
2418        ServletContext ctx = VelocityContextPool.get(servletContextName);
2419
2420        if (ctx == null) {
2421            if (_log.isWarnEnabled()) {
2422                _log.warn(
2423                    "Servlet context not found for theme " +
2424                        theme.getThemeId());
2425            }
2426
2427            return null;
2428        }
2429
2430        File cssPath = null;
2431        File imagesPath = null;
2432        File javaScriptPath = null;
2433        File templatesPath = null;
2434
2435        if (!theme.isLoadFromServletContext()) {
2436            ThemeLoader themeLoader = ThemeLoaderFactory.getThemeLoader(
2437                servletContextName);
2438
2439            if (themeLoader == null) {
2440                _log.error(
2441                    servletContextName + " does not map to a theme loader");
2442            }
2443            else {
2444                String realPath =
2445                    themeLoader.getFileStorage().getPath() + "/" +
2446                        theme.getName();
2447
2448                cssPath = new File(realPath + "/css");
2449                imagesPath = new File(realPath + "/images");
2450                javaScriptPath = new File(realPath + "/javascript");
2451                templatesPath = new File(realPath + "/templates");
2452            }
2453        }
2454        else {
2455            cssPath = new File(ctx.getRealPath(theme.getCssPath()));
2456            imagesPath = new File(ctx.getRealPath(theme.getImagesPath()));
2457            javaScriptPath = new File(
2458                ctx.getRealPath(theme.getJavaScriptPath()));
2459            templatesPath = new File(ctx.getRealPath(theme.getTemplatesPath()));
2460        }
2461
2462        exportThemeFiles("css", cssPath, zipWriter);
2463        exportThemeFiles("images", imagesPath, zipWriter);
2464        exportThemeFiles("javascript", javaScriptPath, zipWriter);
2465        exportThemeFiles("templates", templatesPath, zipWriter);
2466
2467        return zipWriter.finish();
2468    }
2469
2470    protected void exportThemeFiles(String path, File dir, ZipWriter zipWriter)
2471        throws IOException {
2472
2473        if ((dir == null) || (!dir.exists())) {
2474            return;
2475        }
2476
2477        File[] files = dir.listFiles();
2478
2479        for (int i = 0; i < files.length; i++) {
2480            File file = files[i];
2481
2482            if (file.isDirectory()) {
2483                exportThemeFiles(path + "/" + file.getName(), file, zipWriter);
2484            }
2485            else {
2486                zipWriter.addEntry(
2487                    path + "/" + file.getName(), FileUtil.getBytes(file));
2488            }
2489        }
2490    }
2491
2492    protected void exportUserPermissions(
2493            LayoutCache layoutCache, long companyId, long groupId,
2494            String resourceName, String resourcePrimKey, Element parentEl)
2495        throws PortalException, SystemException {
2496
2497        StopWatch stopWatch = null;
2498
2499        if (_log.isDebugEnabled()) {
2500            stopWatch = new StopWatch();
2501
2502            stopWatch.start();
2503        }
2504
2505        Element userPermissionsEl = DocumentHelper.createElement(
2506            "user-permissions");
2507
2508        List users = layoutCache.getGroupUsers(groupId);
2509
2510        for (int i = 0; i < users.size(); i++) {
2511            User user = (User)users.get(i);
2512
2513            String emailAddress = user.getEmailAddress();
2514
2515            Element userActionsEl =
2516                DocumentHelper.createElement("user-actions");
2517
2518            List permissions = permissionLocalService.getUserPermissions(
2519                user.getUserId(), companyId, resourceName,
2520                ResourceImpl.SCOPE_INDIVIDUAL, resourcePrimKey);
2521
2522            List actions = ResourceActionsUtil.getActions(permissions);
2523
2524            for (int j = 0; j < actions.size(); j++) {
2525                String action = (String)actions.get(j);
2526
2527                Element actionKeyEl = userActionsEl.addElement("action-key");
2528
2529                actionKeyEl.addText(action);
2530            }
2531
2532            if (!userActionsEl.elements().isEmpty()) {
2533                userActionsEl.addAttribute("email-address", emailAddress);
2534                userPermissionsEl.add(userActionsEl);
2535            }
2536        }
2537
2538        if (!userPermissionsEl.elements().isEmpty()) {
2539            parentEl.add(userPermissionsEl);
2540        }
2541
2542        if (_log.isDebugEnabled()) {
2543            _log.debug(
2544                "Export user permissions for {" + resourceName + ", " +
2545                    resourcePrimKey + "} with " + users.size() +
2546                        " users takes " + stopWatch.getTime() + " ms");
2547        }
2548    }
2549
2550    protected void exportUserRoles(
2551            LayoutCache layoutCache, long companyId, long groupId,
2552            String resourceName, Element parentEl)
2553        throws PortalException, SystemException {
2554
2555        Element userRolesEl = DocumentHelper.createElement("user-roles");
2556
2557        List users = layoutCache.getGroupUsers(groupId);
2558
2559        for (int i = 0; i < users.size(); i++) {
2560            User user = (User)users.get(i);
2561
2562            long userId = user.getUserId();
2563            String emailAddress = user.getEmailAddress();
2564
2565            List userRoles = layoutCache.getUserRoles(userId);
2566
2567            Element userEl = exportRoles(
2568                companyId, resourceName, ResourceImpl.SCOPE_GROUP,
2569                String.valueOf(groupId), userRolesEl, "user", userRoles);
2570
2571            if (userEl.elements().isEmpty()) {
2572                userRolesEl.remove(userEl);
2573            }
2574            else {
2575                userEl.addAttribute("email-address", emailAddress);
2576            }
2577        }
2578
2579        if (!userRolesEl.elements().isEmpty()) {
2580            parentEl.add(userRolesEl);
2581        }
2582    }
2583
2584    protected void fixTypeSettings(Layout layout) {
2585        if (layout.getType().equals(LayoutImpl.TYPE_URL)) {
2586            Properties typeSettings = layout.getTypeSettingsProperties();
2587
2588            String url = GetterUtil.getString(typeSettings.getProperty("url"));
2589
2590            String friendlyURLPrivateGroupPath =
2591                PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_GROUP_SERVLET_MAPPING;
2592            String friendlyURLPrivateUserPath =
2593                PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING;
2594            String friendlyURLPublicPath =
2595                PropsValues.LAYOUT_FRIENDLY_URL_PUBLIC_SERVLET_MAPPING;
2596
2597            if (url.startsWith(friendlyURLPrivateGroupPath) ||
2598                url.startsWith(friendlyURLPrivateUserPath) ||
2599                url.startsWith(friendlyURLPublicPath)) {
2600
2601                int x = url.indexOf(StringPool.SLASH, 1);
2602
2603                if (x > 0) {
2604                    int y = url.indexOf(StringPool.SLASH, x + 1);
2605
2606                    if (y > x) {
2607                        String fixedUrl = url.substring(0, x) +
2608
2609                        layout.getGroup().getFriendlyURL() +
2610
2611                        url.substring(y);
2612
2613                        typeSettings.setProperty("url", fixedUrl);
2614                    }
2615                }
2616            }
2617        }
2618    }
2619
2620    protected List getActions(Element el) {
2621        List actions = new ArrayList();
2622
2623        Iterator itr = el.elements("action-key").iterator();
2624
2625        while (itr.hasNext()) {
2626            Element actionEl = (Element)itr.next();
2627
2628            actions.add(actionEl.getText());
2629        }
2630
2631        return actions;
2632    }
2633
2634    protected String getFriendlyURL(String friendlyURL) {
2635        return Normalizer.normalizeToAscii(friendlyURL.trim().toLowerCase());
2636    }
2637
2638    protected long getNextLayoutId(long groupId, boolean privateLayout)
2639        throws SystemException {
2640
2641        long layoutId = 0;
2642
2643        List layouts = layoutPersistence.findByG_P(groupId, privateLayout);
2644
2645        for (int i = 0; i < layouts.size(); i++) {
2646            Layout curLayout = (Layout)layouts.get(i);
2647
2648            long curLayoutId = curLayout.getLayoutId();
2649
2650            if (curLayoutId > layoutId) {
2651                layoutId = curLayoutId;
2652            }
2653        }
2654
2655        return ++layoutId;
2656    }
2657
2658    protected int getNextPriority(
2659            long groupId, boolean privateLayout, long parentLayoutId)
2660        throws SystemException {
2661
2662        List layouts = layoutPersistence.findByG_P_P(
2663            groupId, privateLayout, parentLayoutId);
2664
2665        if (layouts.size() == 0) {
2666            return 0;
2667        }
2668
2669        Layout layout = (Layout)layouts.get(layouts.size() - 1);
2670
2671        return layout.getPriority() + 1;
2672    }
2673
2674    protected long getParentLayoutId(
2675            long groupId, boolean privateLayout, long parentLayoutId)
2676        throws PortalException, SystemException {
2677
2678        if (parentLayoutId != LayoutImpl.DEFAULT_PARENT_LAYOUT_ID) {
2679
2680            // Ensure parent layout exists
2681
2682            try {
2683                layoutPersistence.findByG_P_L(
2684                    groupId, privateLayout, parentLayoutId);
2685            }
2686            catch (NoSuchLayoutException nsfe) {
2687                parentLayoutId = LayoutImpl.DEFAULT_PARENT_LAYOUT_ID;
2688            }
2689        }
2690
2691        return parentLayoutId;
2692    }
2693
2694    protected boolean hasRole(List roles, String roleName) {
2695        if ((roles == null) || (roles.size() == 0)) {
2696            return false;
2697        }
2698
2699        for (int i = 0; i < roles.size(); i++) {
2700            Role role = (Role)roles.get(i);
2701
2702            if (role.getName().equals(roleName)) {
2703                return true;
2704            }
2705        }
2706
2707        return false;
2708    }
2709
2710    protected void importGroupPermissions(
2711            LayoutCache layoutCache, long companyId, long groupId,
2712            String resourceName, String resourcePrimKey, Element parentEl,
2713            String elName, boolean portletActions)
2714        throws PortalException, SystemException {
2715
2716        Element actionEl = parentEl.element(elName);
2717
2718        if (actionEl == null) {
2719            return;
2720        }
2721
2722        List actions = getActions(actionEl);
2723
2724        Resource resource = layoutCache.getResource(
2725            companyId, groupId, resourceName, ResourceImpl.SCOPE_INDIVIDUAL,
2726            resourcePrimKey, portletActions);
2727
2728        permissionLocalService.setGroupPermissions(
2729            groupId, (String[])actions.toArray(new String[0]),
2730            resource.getResourceId());
2731    }
2732
2733    protected void importGroupRoles(
2734            LayoutCache layoutCache, long companyId, long groupId,
2735            String resourceName, String entityName,
2736            Element parentEl)
2737        throws PortalException, SystemException {
2738
2739        Element entityRolesEl = parentEl.element(entityName + "-roles");
2740
2741        if (entityRolesEl == null) {
2742            return;
2743        }
2744
2745        importRolePermissions(
2746            layoutCache, companyId, resourceName, ResourceImpl.SCOPE_GROUP,
2747            String.valueOf(groupId), entityRolesEl, true);
2748    }
2749
2750    protected void importInheritedPermissions(
2751            LayoutCache layoutCache, long companyId, String resourceName,
2752            String resourcePrimKey, Element permissionsEl, String entityName,
2753            boolean portletActions)
2754        throws PortalException, SystemException {
2755
2756        Element entityPermissionsEl = permissionsEl.element(
2757            entityName + "-permissions");
2758
2759        if (entityPermissionsEl == null) {
2760            return;
2761        }
2762
2763        List actionsEls = entityPermissionsEl.elements(
2764            entityName + "-actions");
2765
2766        for (int i = 0; i < actionsEls.size(); i++) {
2767            Element actionEl = (Element)actionsEls.get(i);
2768
2769            String name = actionEl.attributeValue("name");
2770
2771            long entityGroupId = layoutCache.getEntityGroupId(
2772                companyId, entityName, name);
2773
2774            if (entityGroupId == 0) {
2775                _log.warn(
2776                    "Ignore inherited permissions for entity " + entityName +
2777                        " with name " + name);
2778            }
2779            else {
2780                Element parentEl = DocumentHelper.createElement("parent");
2781
2782                parentEl.add(actionEl.createCopy());
2783
2784                importGroupPermissions(
2785                    layoutCache, companyId, entityGroupId, resourceName,
2786                    resourcePrimKey, parentEl, entityName + "-actions",
2787                    portletActions);
2788            }
2789        }
2790    }
2791
2792    protected void importInheritedRoles(
2793            LayoutCache layoutCache, long companyId, long groupId,
2794            String resourceName, String entityName, Element parentEl)
2795        throws PortalException, SystemException {
2796
2797        Element entityRolesEl = parentEl.element(entityName + "-roles");
2798
2799        if (entityRolesEl == null) {
2800            return;
2801        }
2802
2803        List entityEls = entityRolesEl.elements(entityName);
2804
2805        for (int i = 0; i < entityEls.size(); i++) {
2806            Element entityEl = (Element)entityEls.get(i);
2807
2808            String name = entityEl.attributeValue("name");
2809
2810            long entityGroupId = layoutCache.getEntityGroupId(
2811                companyId, entityName, name);
2812
2813            if (entityGroupId == 0) {
2814                _log.warn(
2815                    "Ignore inherited roles for entity " + entityName +
2816                        " with name " + name);
2817            }
2818            else {
2819                importRolePermissions(
2820                    layoutCache, companyId, resourceName,
2821                    ResourceImpl.SCOPE_GROUP, String.valueOf(groupId), entityEl,
2822                    false);
2823            }
2824        }
2825    }
2826
2827    protected void importLayoutPermissions(
2828            LayoutCache layoutCache, long companyId, long groupId,
2829            Group guestGroup, Layout layout, Element permissionsEl,
2830            boolean importUserPermissions)
2831        throws PortalException, SystemException {
2832
2833        String resourceName = Layout.class.getName();
2834        String resourcePrimKey = String.valueOf(layout.getPlid());
2835
2836        importGroupPermissions(
2837            layoutCache, companyId, groupId, resourceName, resourcePrimKey,
2838            permissionsEl, "community-actions", false);
2839
2840        if (groupId != guestGroup.getGroupId()) {
2841            importGroupPermissions(
2842                layoutCache, companyId, guestGroup.getGroupId(), resourceName,
2843                resourcePrimKey, permissionsEl, "guest-actions", false);
2844        }
2845
2846        if (importUserPermissions) {
2847            importUserPermissions(
2848                layoutCache, companyId, groupId, resourceName, resourcePrimKey,
2849                permissionsEl, false);
2850        }
2851
2852        importInheritedPermissions(
2853            layoutCache, companyId, resourceName, resourcePrimKey,
2854            permissionsEl, "organization", false);
2855
2856        importInheritedPermissions(
2857            layoutCache, companyId, resourceName, resourcePrimKey,
2858            permissionsEl, "location", false);
2859
2860        importInheritedPermissions(
2861            layoutCache, companyId, resourceName, resourcePrimKey,
2862            permissionsEl, "user-group", false);
2863    }
2864
2865    protected void importLayoutRoles(
2866            LayoutCache layoutCache, long companyId, long groupId,
2867            Element rolesEl)
2868        throws PortalException, SystemException {
2869
2870        String resourceName = Layout.class.getName();
2871
2872        importGroupRoles(
2873            layoutCache, companyId, groupId, resourceName, "community",
2874            rolesEl);
2875
2876        importUserRoles(layoutCache, companyId, groupId, resourceName, rolesEl);
2877
2878        importInheritedRoles(
2879            layoutCache, companyId, groupId, resourceName, "organization",
2880            rolesEl);
2881
2882        importInheritedRoles(
2883            layoutCache, companyId, groupId, resourceName, "location", rolesEl);
2884
2885        importInheritedRoles(
2886            layoutCache, companyId, groupId, resourceName, "user-group",
2887            rolesEl);
2888    }
2889
2890    protected void importPortletData(
2891            PortletDataContext context, Layout layout, Element parentEl)
2892        throws PortalException, SystemException {
2893
2894        Iterator itr = parentEl.elements("portlet-data").iterator();
2895
2896        while (itr.hasNext()) {
2897            Element el = (Element)itr.next();
2898
2899            String portletId = el.attributeValue("portlet-id");
2900
2901            try {
2902                PortletPreferences portletPreferences =
2903                    portletPreferencesPersistence.findByO_O_P_P(
2904                        PortletKeys.PREFS_OWNER_ID_DEFAULT,
2905                        PortletKeys.PREFS_OWNER_TYPE_LAYOUT, layout.getPlid(),
2906                        portletId);
2907
2908                String preferences = importPortletData(
2909                    context, portletId, portletPreferences, el);
2910
2911                if (preferences != null) {
2912                    portletPreferences.setPreferences(preferences);
2913
2914                    portletPreferencesPersistence.update(portletPreferences);
2915                }
2916            }
2917            catch (NoSuchPortletPreferencesException nsppe) {
2918            }
2919        }
2920    }
2921
2922    protected String importPortletData(
2923            PortletDataContext context, String portletId,
2924            PortletPreferences portletPreferences, Element parentEl)
2925        throws PortalException, SystemException {
2926
2927        Portlet portlet = portletLocalService.getPortletById(
2928            context.getCompanyId(), portletId);
2929
2930        if (portlet == null) {
2931            if (_log.isDebugEnabled()) {
2932                _log.debug(
2933                    "Do not import portlet data for " + portletId +
2934                        " because the portlet does not exist");
2935            }
2936
2937            return null;
2938        }
2939
2940        PortletDataHandler portletDataHandler =
2941            portlet.getPortletDataHandlerInstance();
2942
2943        if (portletDataHandler == null) {
2944            if (_log.isDebugEnabled()) {
2945                _log.debug(
2946                    "Do not import portlet data for " + portletId +
2947                        " because the portlet does not have a " +
2948                            "PortletDataHandler");
2949            }
2950
2951            return null;
2952        }
2953
2954        if (_log.isDebugEnabled()) {
2955            _log.debug("Importing data for " + portletId);
2956        }
2957
2958        PortletPreferencesImpl prefsImpl =
2959            (PortletPreferencesImpl)PortletPreferencesSerializer.fromDefaultXML(
2960                portletPreferences.getPreferences());
2961
2962        prefsImpl = (PortletPreferencesImpl)portletDataHandler.importData(
2963            context, portletId, prefsImpl, parentEl.getText());
2964
2965        if (prefsImpl == null) {
2966            return null;
2967        }
2968
2969        return PortletPreferencesSerializer.toXML(prefsImpl);
2970    }
2971
2972    protected void importPortletPermissions(
2973            LayoutCache layoutCache, long companyId, long groupId,
2974            Group guestGroup, Layout layout, Element permissionsEl,
2975            boolean importUserPermissions)
2976        throws PortalException, SystemException {
2977
2978        Iterator itr = permissionsEl.elements("portlet").iterator();
2979
2980        while (itr.hasNext()) {
2981            Element portletEl = (Element)itr.next();
2982
2983            String portletId = portletEl.attributeValue("portlet-id");
2984
2985            String resourceName = PortletImpl.getRootPortletId(portletId);
2986            String resourcePrimKey = PortletPermissionUtil.getPrimaryKey(
2987                layout.getPlid(), portletId);
2988
2989            Portlet portlet = portletLocalService.getPortletById(
2990                companyId, resourceName);
2991
2992            if (portlet == null) {
2993                if (_log.isDebugEnabled()) {
2994                    _log.debug(
2995                        "Do not import portlet permissions for " + portletId +
2996                            " because the portlet does not exist");
2997                }
2998            }
2999            else {
3000                importGroupPermissions(
3001                    layoutCache, companyId, groupId, resourceName,
3002                    resourcePrimKey, portletEl, "community-actions", true);
3003
3004                if (groupId != guestGroup.getGroupId()) {
3005                    importGroupPermissions(
3006                        layoutCache, companyId, guestGroup.getGroupId(),
3007                        resourceName, resourcePrimKey, portletEl,
3008                        "guest-actions", true);
3009                }
3010
3011                if (importUserPermissions) {
3012                    importUserPermissions(
3013                        layoutCache, companyId, groupId, resourceName,
3014                        resourcePrimKey, portletEl, true);
3015                }
3016
3017                importInheritedPermissions(
3018                    layoutCache, companyId, resourceName, resourcePrimKey,
3019                    portletEl, "organization", true);
3020
3021                importInheritedPermissions(
3022                    layoutCache, companyId, resourceName, resourcePrimKey,
3023                    portletEl, "location", true);
3024
3025                importInheritedPermissions(
3026                    layoutCache, companyId, resourceName, resourcePrimKey,
3027                    portletEl, "user-group", true);
3028            }
3029        }
3030    }
3031
3032    protected void importPortletPreferences(
3033            long companyId, long plid, Element parentEl,
3034            boolean importPortletSetup, boolean importUserPreferences)
3035        throws PortalException, SystemException {
3036
3037        long defaultUserId = userLocalService.getDefaultUserId(companyId);
3038
3039        Iterator itr = parentEl.elements("portlet-preferences").iterator();
3040
3041        while (itr.hasNext()) {
3042            Element el = (Element)itr.next();
3043
3044            long ownerId = GetterUtil.getLong(el.attributeValue("owner-id"));
3045            int ownerType = GetterUtil.getInteger(
3046                el.attributeValue("owner-type"));
3047
3048            if (ownerType == PortletKeys.PREFS_OWNER_TYPE_COMPANY) {
3049                continue;
3050            }
3051
3052            if ((ownerType != PortletKeys.PREFS_OWNER_TYPE_USER) &&
3053                !importPortletSetup) {
3054
3055                continue;
3056            }
3057
3058            if ((ownerType == PortletKeys.PREFS_OWNER_TYPE_USER) &&
3059                (ownerId != PortletKeys.PREFS_OWNER_ID_DEFAULT) &&
3060                !importUserPreferences) {
3061
3062                continue;
3063            }
3064
3065            if (ownerType == PortletKeys.PREFS_OWNER_TYPE_GROUP) {
3066                plid = PortletKeys.PREFS_PLID_SHARED;
3067            }
3068
3069            boolean defaultUser = GetterUtil.getBoolean(
3070                el.attributeValue("default-user"));
3071            String portletId = el.attributeValue("portlet-id");
3072            String preferences = el.elementText("preferences");
3073
3074            if (defaultUser) {
3075                ownerId = defaultUserId;
3076            }
3077
3078            try {
3079                portletPreferencesLocalService.deletePortletPreferences(
3080                    ownerId, ownerType, plid, portletId);
3081            }
3082            catch (NoSuchPortletPreferencesException nsppe) {
3083            }
3084
3085            long portletPreferencesId = counterLocalService.increment();
3086
3087            PortletPreferences portletPreferences =
3088                portletPreferencesPersistence.create(portletPreferencesId);
3089
3090            portletPreferences.setOwnerId(ownerId);
3091            portletPreferences.setOwnerType(ownerType);
3092            portletPreferences.setPlid(plid);
3093            portletPreferences.setPortletId(portletId);
3094
3095            portletPreferences.setPreferences(preferences);
3096
3097            portletPreferencesPersistence.update(portletPreferences);
3098        }
3099    }
3100
3101    protected void importPortletRoles(
3102            LayoutCache layoutCache, long companyId, long groupId,
3103            Element rolesEl)
3104        throws PortalException, SystemException {
3105
3106        Iterator itr = rolesEl.elements("portlet").iterator();
3107
3108        while (itr.hasNext()) {
3109            Element portletEl = (Element)itr.next();
3110
3111            String portletId = portletEl.attributeValue("portlet-id");
3112
3113            String resourceName = PortletImpl.getRootPortletId(portletId);
3114
3115            Portlet portlet = portletLocalService.getPortletById(
3116                companyId, resourceName);
3117
3118            if (portlet == null) {
3119                if (_log.isDebugEnabled()) {
3120                    _log.debug(
3121                        "Do not import portlet roles for " + portletId +
3122                            " because the portlet does not exist");
3123                }
3124            }
3125            else {
3126                importGroupRoles(
3127                    layoutCache, companyId, groupId, resourceName, "community",
3128                    portletEl);
3129
3130                importUserRoles(
3131                    layoutCache, companyId, groupId, resourceName, portletEl);
3132
3133                importInheritedRoles(
3134                    layoutCache, companyId, groupId, resourceName,
3135                    "organization", portletEl);
3136
3137                importInheritedRoles(
3138                    layoutCache, companyId, groupId, resourceName, "location",
3139                    portletEl);
3140
3141                importInheritedRoles(
3142                    layoutCache, companyId, groupId, resourceName, "user-group",
3143                    portletEl);
3144            }
3145        }
3146    }
3147
3148    protected void importRolePermissions(
3149            LayoutCache layoutCache, long companyId, String resourceName,
3150            int scope, String resourcePrimKey, Element parentEl,
3151            boolean communityRole)
3152        throws PortalException, SystemException {
3153
3154        List roleEls = parentEl.elements("role");
3155
3156        for (int i = 0; i < roleEls.size(); i++) {
3157            Element roleEl = (Element)roleEls.get(i);
3158
3159            String roleName = roleEl.attributeValue("name");
3160
3161            Role role = layoutCache.getRole(companyId, roleName);
3162
3163            if (role == null) {
3164                _log.warn(
3165                    "Ignoring permissions for role with name " + roleName);
3166            }
3167            else {
3168                List actions = getActions(roleEl);
3169
3170                permissionLocalService.setRolePermissions(
3171                    role.getRoleId(), companyId, resourceName, scope,
3172                    resourcePrimKey, (String[])actions.toArray(new String[0]));
3173
3174                if (communityRole) {
3175                    long[] groupIds = {GetterUtil.getLong(resourcePrimKey)};
3176
3177                    groupLocalService.addRoleGroups(role.getRoleId(), groupIds);
3178                }
3179            }
3180        }
3181    }
3182
3183    protected String importTheme(LayoutSet layoutSet, byte[] themeZip)
3184        throws IOException {
3185
3186        ThemeLoader themeLoader = ThemeLoaderFactory.getDefaultThemeLoader();
3187
3188        if (themeLoader == null) {
3189            _log.error("No theme loaders are deployed");
3190
3191            return null;
3192        }
3193
3194        ZipReader zipReader = new ZipReader(new ByteArrayInputStream(themeZip));
3195
3196        Map entries = zipReader.getEntries();
3197
3198        String lookAndFeelXML = new String(
3199            (byte[])entries.get("liferay-look-and-feel.xml"));
3200
3201        String themeId = String.valueOf(layoutSet.getGroupId());
3202
3203        if (layoutSet.isPrivateLayout()) {
3204            themeId += "-private";
3205        }
3206        else {
3207            themeId += "-public";
3208        }
3209
3210        if (PropsValues.THEME_LOADER_NEW_THEME_ID_ON_IMPORT) {
3211            Date now = new Date();
3212
3213            themeId += "-" + Time.getShortTimestamp(now);
3214        }
3215
3216        String themeName = themeId;
3217
3218        lookAndFeelXML = StringUtil.replace(
3219            lookAndFeelXML,
3220            new String[] {
3221                "[$GROUP_ID$]", "[$THEME_ID$]", "[$THEME_NAME$]"
3222            },
3223            new String[] {
3224                String.valueOf(layoutSet.getGroupId()), themeId, themeName
3225            }
3226        );
3227
3228        FileUtil.deltree(themeLoader.getFileStorage() + "/" + themeId);
3229
3230        Iterator itr = entries.entrySet().iterator();
3231
3232        while (itr.hasNext()) {
3233            Map.Entry entry = (Map.Entry)itr.next();
3234
3235            String key = (String)entry.getKey();
3236            byte[] value = (byte[])entry.getValue();
3237
3238            if (key.equals("liferay-look-and-feel.xml")) {
3239                value = lookAndFeelXML.getBytes();
3240            }
3241
3242            FileUtil.write(
3243                themeLoader.getFileStorage() + "/" + themeId + "/" + key,
3244                value);
3245        }
3246
3247        themeLoader.loadThemes();
3248
3249        CommLink commLink = CommLink.getInstance();
3250
3251        MethodWrapper methodWrapper = new MethodWrapper(
3252            ThemeLoaderFactory.class.getName(), "loadThemes");
3253
3254        commLink.send(methodWrapper);
3255
3256        themeId +=
3257            PortletImpl.WAR_SEPARATOR + themeLoader.getServletContextName();
3258
3259        return PortalUtil.getJsSafePortletId(themeId);
3260    }
3261
3262    protected void importUserPermissions(
3263            LayoutCache layoutCache, long companyId, long groupId,
3264            String resourceName, String resourcePrimKey, Element parentEl,
3265            boolean portletActions)
3266        throws PortalException, SystemException {
3267
3268        Element userPermissionsEl = parentEl.element("user-permissions");
3269
3270        if (userPermissionsEl == null) {
3271            return;
3272        }
3273
3274        List userActionsEls = userPermissionsEl.elements("user-actions");
3275
3276        for (int i = 0; i < userActionsEls.size(); i++) {
3277            Element userActionsEl = (Element)userActionsEls.get(i);
3278
3279            String emailAddress = userActionsEl.attributeValue("email-address");
3280
3281            User user = layoutCache.getUser(companyId, groupId, emailAddress);
3282
3283            if (user == null) {
3284                if (_log.isWarnEnabled()) {
3285                    _log.warn(
3286                        "Ignoring permissions for user with email address " +
3287                            emailAddress);
3288                }
3289            }
3290            else {
3291                List actions = getActions(userActionsEl);
3292
3293                Resource resource = layoutCache.getResource(
3294                    companyId, groupId, resourceName,
3295                    ResourceImpl.SCOPE_INDIVIDUAL, resourcePrimKey,
3296                    portletActions);
3297
3298                permissionLocalService.setUserPermissions(
3299                    user.getUserId(), (String[])actions.toArray(new String[0]),
3300                    resource.getResourceId());
3301            }
3302        }
3303    }
3304
3305    protected void importUserRoles(
3306            LayoutCache layoutCache, long companyId, long groupId,
3307            String resourceName, Element parentEl)
3308        throws PortalException, SystemException {
3309
3310        Element userRolesEl = parentEl.element("user-roles");
3311
3312        if (userRolesEl == null) {
3313            return;
3314        }
3315
3316        LinkedHashMap params = new LinkedHashMap();
3317
3318        params.put("usersGroups", new Long(groupId));
3319
3320        List userEls = userRolesEl.elements("user");
3321
3322        for (int i = 0; i < userEls.size(); i++) {
3323            Element userEl = (Element)userEls.get(i);
3324
3325            String emailAddress = userEl.attributeValue("email-address");
3326
3327            User user = layoutCache.getUser(companyId, groupId, emailAddress);
3328
3329            if (user == null) {
3330                if (_log.isWarnEnabled()) {
3331                    _log.warn(
3332                        "Ignoring roles for user with email address " +
3333                            emailAddress);
3334                }
3335            }
3336            else {
3337                importRolePermissions(
3338                    layoutCache, companyId, resourceName,
3339                    ResourceImpl.SCOPE_GROUP, String.valueOf(groupId), userEl,
3340                    false);
3341            }
3342        }
3343    }
3344
3345    protected boolean isDescendant(Layout layout, long layoutId)
3346        throws PortalException, SystemException {
3347
3348        if (layout.getLayoutId() == layoutId) {
3349            return true;
3350        }
3351        else {
3352            Iterator itr = layout.getChildren().iterator();
3353
3354            while (itr.hasNext()) {
3355                Layout childLayout = (Layout)itr.next();
3356
3357                if (isDescendant(childLayout, layoutId)) {
3358                    return true;
3359                }
3360            }
3361
3362            return false;
3363        }
3364    }
3365
3366    protected void readComments(PortletDataContext context, Element root)
3367        throws PortalException, SystemException {
3368
3369        try {
3370            XStream xStream = new XStream();
3371
3372            Iterator itr = root.elements("comments").iterator();
3373
3374            while (itr.hasNext()) {
3375                Element el = (Element)itr.next();
3376
3377                String className = GetterUtil.getString(
3378                    el.attributeValue("class-name"));
3379                long classPK = GetterUtil.getLong(
3380                    el.attributeValue("class-pk"));
3381
3382                Element messagesListEl = el.element("list");
3383
3384                Document tempDoc = DocumentHelper.createDocument();
3385
3386                tempDoc.content().add(messagesListEl.createCopy());
3387
3388                List messages = (List)xStream.fromXML(
3389                    XMLFormatter.toString(tempDoc));
3390
3391                context.addComments(className, new Long(classPK), messages);
3392            }
3393        }
3394        catch (Exception e) {
3395            throw new SystemException(e);
3396        }
3397    }
3398
3399    protected void readRatings(PortletDataContext context, Element root)
3400        throws PortalException, SystemException {
3401
3402        try {
3403            XStream xStream = new XStream();
3404
3405            Iterator itr = root.elements("ratings").iterator();
3406
3407            while (itr.hasNext()) {
3408                Element el = (Element)itr.next();
3409
3410                String className = GetterUtil.getString(
3411                    el.attributeValue("class-name"));
3412                long classPK = GetterUtil.getLong(
3413                    el.attributeValue("class-pk"));
3414
3415                Element entriesListEl = el.element("list");
3416
3417                Document tempDoc = DocumentHelper.createDocument();
3418
3419                tempDoc.content().add(entriesListEl.createCopy());
3420
3421                List entries = (List)xStream.fromXML(
3422                    XMLFormatter.toString(tempDoc));
3423
3424                context.addRatingsEntries(
3425                    className, new Long(classPK), entries);
3426            }
3427        }
3428        catch (Exception e) {
3429            throw new SystemException(e);
3430        }
3431    }
3432
3433    protected void readTags(PortletDataContext context, Element root)
3434        throws PortalException, SystemException {
3435
3436        Iterator itr = root.elements("tags").iterator();
3437
3438        while (itr.hasNext()) {
3439            Element el = (Element)itr.next();
3440
3441            String className = GetterUtil.getString(
3442                el.attributeValue("class-name"));
3443            long classPK = GetterUtil.getLong(el.attributeValue("class-pk"));
3444            String entries = GetterUtil.getString(el.attributeValue("entries"));
3445
3446            context.addTagsEntries(
3447                className, new Long(classPK), StringUtil.split(entries, ","));
3448        }
3449    }
3450
3451    protected void setLocalizedAttributes(
3452        Layout layout, Map localeNamesMap, Map localeTitlesMap) {
3453
3454        Locale[] locales = LanguageUtil.getAvailableLocales();
3455
3456        for (int i = 0; i < locales.length; i++) {
3457            String name = (String)localeNamesMap.get(locales[i]);
3458            String title = (String)localeTitlesMap.get(locales[i]);
3459
3460            layout.setName(name, locales[i]);
3461            layout.setTitle(title, locales[i]);
3462        }
3463    }
3464
3465    protected void validate(
3466            long groupId, boolean privateLayout, long layoutId,
3467            long parentLayoutId, String type, boolean hidden,
3468            String friendlyURL)
3469        throws PortalException, SystemException {
3470
3471        boolean firstLayout = false;
3472
3473        if (parentLayoutId == LayoutImpl.DEFAULT_PARENT_LAYOUT_ID) {
3474            List layouts = layoutPersistence.findByG_P_P(
3475                groupId, privateLayout, parentLayoutId, 0, 1);
3476
3477            if (layouts.size() == 0) {
3478                firstLayout = true;
3479            }
3480            else {
3481                long firstLayoutId = ((Layout)layouts.get(0)).getLayoutId();
3482
3483                if (firstLayoutId == layoutId) {
3484                    firstLayout = true;
3485                }
3486            }
3487        }
3488
3489        if (firstLayout) {
3490            validateFirstLayout(type, hidden);
3491        }
3492
3493        if (!PortalUtil.isLayoutParentable(type)) {
3494            if (layoutPersistence.countByG_P_P(
3495                    groupId, privateLayout, layoutId) > 0) {
3496
3497                throw new LayoutTypeException(
3498                    LayoutTypeException.NOT_PARENTABLE);
3499            }
3500        }
3501
3502        if (Validator.isNotNull(friendlyURL)) {
3503            int exceptionType = LayoutImpl.validateFriendlyURL(friendlyURL);
3504
3505            if (exceptionType != -1) {
3506                throw new LayoutFriendlyURLException(exceptionType);
3507            }
3508
3509            try {
3510                Layout layout = layoutPersistence.findByG_P_F(
3511                    groupId, privateLayout, friendlyURL);
3512
3513                if (layout.getLayoutId() != layoutId) {
3514                    throw new LayoutFriendlyURLException(
3515                        LayoutFriendlyURLException.DUPLICATE);
3516                }
3517            }
3518            catch (NoSuchLayoutException nsle) {
3519            }
3520
3521            LayoutImpl.validateFriendlyURLKeyword(friendlyURL);
3522
3523            List friendlyURLMappers =
3524                portletLocalService.getFriendlyURLMappers();
3525
3526            Iterator itr = friendlyURLMappers.iterator();
3527
3528            while (itr.hasNext()) {
3529                FriendlyURLMapper friendlyURLMapper =
3530                    (FriendlyURLMapper)itr.next();
3531
3532                if (friendlyURL.indexOf(friendlyURLMapper.getMapping()) != -1) {
3533                    LayoutFriendlyURLException lfurle =
3534                        new LayoutFriendlyURLException(
3535                            LayoutFriendlyURLException.KEYWORD_CONFLICT);
3536
3537                    lfurle.setKeywordConflict(friendlyURLMapper.getMapping());
3538
3539                    throw lfurle;
3540                }
3541            }
3542
3543        }
3544    }
3545
3546    protected void validateFirstLayout(String type, boolean hidden)
3547        throws PortalException {
3548
3549        if (!type.equals(LayoutImpl.TYPE_PORTLET)) {
3550            throw new LayoutTypeException(LayoutTypeException.FIRST_LAYOUT);
3551        }
3552
3553        if (hidden) {
3554            throw new LayoutHiddenException();
3555        }
3556    }
3557
3558    protected void validateParentLayoutId(
3559            long groupId, boolean privateLayout, long layoutId,
3560            long parentLayoutId)
3561        throws PortalException, SystemException {
3562
3563        Layout layout = layoutPersistence.findByG_P_L(
3564            groupId, privateLayout, layoutId);
3565
3566        if (parentLayoutId != layout.getParentLayoutId()) {
3567
3568            // Layouts can always be moved to the root level
3569
3570            if (parentLayoutId == LayoutImpl.DEFAULT_PARENT_LAYOUT_ID) {
3571                return;
3572            }
3573
3574            // Layout cannot become a child of a layout that is not parentable
3575
3576            Layout parentLayout = layoutPersistence.findByG_P_L(
3577                groupId, privateLayout, parentLayoutId);
3578
3579            if (!PortalUtil.isLayoutParentable(parentLayout)) {
3580                throw new LayoutParentLayoutIdException(
3581                    LayoutParentLayoutIdException.NOT_PARENTABLE);
3582            }
3583
3584            // Layout cannot become descendant of itself
3585
3586            if (isDescendant(layout, parentLayoutId)) {
3587                throw new LayoutParentLayoutIdException(
3588                    LayoutParentLayoutIdException.SELF_DESCENDANT);
3589            }
3590
3591            // If layout is moved, the new first layout must be valid
3592
3593            if (layout.getParentLayoutId() ==
3594                    LayoutImpl.DEFAULT_PARENT_LAYOUT_ID) {
3595
3596                List layouts = layoutPersistence.findByG_P_P(
3597                    groupId, privateLayout,
3598                    LayoutImpl.DEFAULT_PARENT_LAYOUT_ID, 0, 2);
3599
3600                // You can only reach this point if there are more than two
3601                // layouts at the root level because of the descendant check
3602
3603                long firstLayoutId = ((Layout)layouts.get(0)).getLayoutId();
3604
3605                if (firstLayoutId == layoutId) {
3606                    Layout secondLayout = (Layout)layouts.get(1);
3607
3608                    try {
3609                        validateFirstLayout(
3610                            secondLayout.getType(), secondLayout.getHidden());
3611                    }
3612                    catch (LayoutHiddenException lhe) {
3613                        throw new LayoutParentLayoutIdException(
3614                            LayoutParentLayoutIdException.FIRST_LAYOUT_HIDDEN);
3615                    }
3616                    catch (LayoutTypeException lte) {
3617                        throw new LayoutParentLayoutIdException(
3618                            LayoutParentLayoutIdException.FIRST_LAYOUT_TYPE);
3619                    }
3620                }
3621            }
3622        }
3623    }
3624
3625    private static Log _log = LogFactory.getLog(LayoutLocalServiceImpl.class);
3626
3627}