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.ReleaseInfo;
46  import com.liferay.portal.kernel.util.StringPool;
47  import com.liferay.portal.kernel.util.StringUtil;
48  import com.liferay.portal.kernel.util.Validator;
49  import com.liferay.portal.kernel.zip.ZipReader;
50  import com.liferay.portal.kernel.zip.ZipWriter;
51  import com.liferay.portal.lar.AlwaysCurrentUserIdStrategy;
52  import com.liferay.portal.lar.CurrentUserIdStrategy;
53  import com.liferay.portal.lar.PortletDataContextImpl;
54  import com.liferay.portal.model.Group;
55  import com.liferay.portal.model.Layout;
56  import com.liferay.portal.model.LayoutReference;
57  import com.liferay.portal.model.LayoutSet;
58  import com.liferay.portal.model.LayoutTypePortlet;
59  import com.liferay.portal.model.Portlet;
60  import com.liferay.portal.model.PortletPreferences;
61  import com.liferay.portal.model.Resource;
62  import com.liferay.portal.model.Role;
63  import com.liferay.portal.model.Theme;
64  import com.liferay.portal.model.User;
65  import com.liferay.portal.model.impl.ColorSchemeImpl;
66  import com.liferay.portal.model.impl.GroupImpl;
67  import com.liferay.portal.model.impl.LayoutImpl;
68  import com.liferay.portal.model.impl.PortletImpl;
69  import com.liferay.portal.model.impl.ResourceImpl;
70  import com.liferay.portal.security.permission.ResourceActionsUtil;
71  import com.liferay.portal.service.LayoutLocalServiceUtil;
72  import com.liferay.portal.service.base.LayoutLocalServiceBaseImpl;
73  import com.liferay.portal.service.permission.PortletPermissionUtil;
74  import com.liferay.portal.theme.ThemeLoader;
75  import com.liferay.portal.theme.ThemeLoaderFactory;
76  import com.liferay.portal.util.ContentUtil;
77  import com.liferay.portal.util.PortalUtil;
78  import com.liferay.portal.util.PortletKeys;
79  import com.liferay.portal.util.PropsValues;
80  import com.liferay.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(LocaleUtil.getDefault()),
1484                    folder.getDescription());
1485            }
1486        }
1487        catch (NoSuchFolderException nsfe) {
1488        }
1489
1490        return layout;
1491    }
1492
1493    public Layout updateLayout(
1494            long groupId, boolean privateLayout, long layoutId,
1495            String typeSettings)
1496        throws PortalException, SystemException {
1497
1498        Layout layout = layoutPersistence.findByG_P_L(
1499            groupId, privateLayout, layoutId);
1500
1501        layout.setTypeSettings(typeSettings);
1502
1503        layoutPersistence.update(layout);
1504
1505        return layout;
1506    }
1507
1508    public Layout updateLookAndFeel(
1509            long groupId, boolean privateLayout, long layoutId, String themeId,
1510            String colorSchemeId, String css, boolean wapTheme)
1511        throws PortalException, SystemException {
1512
1513        Layout layout = layoutPersistence.findByG_P_L(
1514            groupId, privateLayout, layoutId);
1515
1516        if (wapTheme) {
1517            layout.setWapThemeId(themeId);
1518            layout.setWapColorSchemeId(colorSchemeId);
1519        }
1520        else {
1521            layout.setThemeId(themeId);
1522            layout.setColorSchemeId(colorSchemeId);
1523            layout.setCss(css);
1524        }
1525
1526        layoutPersistence.update(layout);
1527
1528        return layout;
1529    }
1530
1531    public Layout updateName(long plid, String name, String languageId)
1532        throws PortalException, SystemException {
1533
1534        Layout layout = layoutPersistence.findByPrimaryKey(plid);
1535
1536        return updateName(layout, name, languageId);
1537    }
1538
1539    public Layout updateName(
1540            long groupId, boolean privateLayout, long layoutId, String name,
1541            String languageId)
1542        throws PortalException, SystemException {
1543
1544        Layout layout = layoutPersistence.findByG_P_L(
1545            groupId, privateLayout, layoutId);
1546
1547        return updateName(layout, name, languageId);
1548    }
1549
1550    public Layout updateName(Layout layout, String name, String languageId)
1551        throws PortalException, SystemException {
1552
1553        layout.setName(name, LocaleUtil.fromLanguageId(languageId));
1554
1555        layoutPersistence.update(layout);
1556
1557        try {
1558            if (layout.getDlFolderId() > 0) {
1559                DLFolder folder = dlFolderLocalService.getFolder(
1560                    layout.getDlFolderId());
1561
1562                dlFolderLocalService.updateFolder(
1563                    folder.getFolderId(), folder.getParentFolderId(),
1564                    layout.getName(LocaleUtil.getDefault()),
1565                    folder.getDescription());
1566            }
1567        }
1568        catch (NoSuchFolderException nsfe) {
1569        }
1570
1571        return layout;
1572    }
1573
1574    public Layout updateParentLayoutId(long plid, long parentPlid)
1575        throws PortalException, SystemException {
1576
1577        Layout layout = layoutPersistence.findByPrimaryKey(plid);
1578
1579        long parentLayoutId = LayoutImpl.DEFAULT_PARENT_LAYOUT_ID;
1580
1581        if (parentPlid > 0) {
1582            try {
1583                Layout parentLayout = layoutPersistence.findByPrimaryKey(
1584                    parentPlid);
1585
1586                parentLayoutId = parentLayout.getLayoutId();
1587            }
1588            catch (NoSuchLayoutException nsle) {
1589            }
1590        }
1591
1592        parentLayoutId = getParentLayoutId(
1593            layout.getGroupId(), layout.isPrivateLayout(), parentLayoutId);
1594
1595        validateParentLayoutId(
1596            layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(),
1597            parentLayoutId);
1598
1599        if (parentLayoutId != layout.getParentLayoutId()) {
1600            int priority = getNextPriority(
1601                layout.getGroupId(), layout.isPrivateLayout(), parentLayoutId);
1602
1603            layout.setPriority(priority);
1604        }
1605
1606        layout.setParentLayoutId(parentLayoutId);
1607
1608        layoutPersistence.update(layout);
1609
1610        return layout;
1611    }
1612
1613    public Layout updateParentLayoutId(
1614            long groupId, boolean privateLayout, long layoutId,
1615            long parentLayoutId)
1616        throws PortalException, SystemException {
1617
1618        parentLayoutId = getParentLayoutId(
1619            groupId, privateLayout, parentLayoutId);
1620
1621        validateParentLayoutId(
1622            groupId, privateLayout, layoutId, parentLayoutId);
1623
1624        Layout layout = layoutPersistence.findByG_P_L(
1625            groupId, privateLayout, layoutId);
1626
1627        if (parentLayoutId != layout.getParentLayoutId()) {
1628            layout.setPriority(
1629                getNextPriority(groupId, privateLayout, parentLayoutId));
1630        }
1631
1632        layout.setParentLayoutId(parentLayoutId);
1633
1634        layoutPersistence.update(layout);
1635
1636        return layout;
1637    }
1638
1639    public Layout updatePriority(long plid, int priority)
1640        throws PortalException, SystemException {
1641
1642        Layout layout = layoutPersistence.findByPrimaryKey(plid);
1643
1644        return updatePriority(layout, priority);
1645    }
1646
1647    public Layout updatePriority(
1648            long groupId, boolean privateLayout, long layoutId, int priority)
1649        throws PortalException, SystemException {
1650
1651        Layout layout = layoutPersistence.findByG_P_L(
1652            groupId, privateLayout, layoutId);
1653
1654        return updatePriority(layout, priority);
1655    }
1656
1657    public Layout updatePriority(Layout layout, int priority)
1658        throws PortalException, SystemException {
1659
1660        if (layout.getPriority() == priority) {
1661            return layout;
1662        }
1663
1664        boolean lessThan = false;
1665
1666        if (layout.getPriority() < priority) {
1667            lessThan = true;
1668        }
1669
1670        layout.setPriority(priority);
1671
1672        layoutPersistence.update(layout);
1673
1674        priority = 0;
1675
1676        List layouts = layoutPersistence.findByG_P_P(
1677            layout.getGroupId(), layout.isPrivateLayout(),
1678            layout.getParentLayoutId());
1679
1680        Collections.sort(
1681            layouts, new LayoutPriorityComparator(layout, lessThan));
1682
1683        Iterator itr = layouts.iterator();
1684
1685        while (itr.hasNext()) {
1686            Layout curLayout = (Layout)itr.next();
1687
1688            curLayout.setPriority(priority++);
1689
1690            layoutPersistence.update(curLayout);
1691
1692            if (curLayout.equals(layout)) {
1693                layout = curLayout;
1694            }
1695        }
1696
1697        return layout;
1698    }
1699
1700    protected void deleteMissingLayouts(
1701            long groupId, boolean privateLayout, Set newLayoutIds)
1702        throws PortalException, SystemException {
1703
1704        // Layouts
1705
1706        if (_log.isDebugEnabled()) {
1707            if (newLayoutIds.size() > 0) {
1708                _log.debug("Delete missing layouts");
1709            }
1710        }
1711
1712        List layouts = layoutPersistence.findByG_P(groupId, privateLayout);
1713
1714        Iterator itr = layouts.iterator();
1715
1716        while (itr.hasNext()) {
1717            Layout layout = (Layout)itr.next();
1718
1719            if (!newLayoutIds.contains(new Long(layout.getLayoutId()))) {
1720                try {
1721                    deleteLayout(layout, false);
1722                }
1723                catch (NoSuchLayoutException nsle) {
1724                }
1725            }
1726        }
1727
1728        // Layout set
1729
1730        layoutSetLocalService.updatePageCount(groupId, privateLayout);
1731    }
1732
1733    protected void deletePortletData(
1734            PortletDataContext context, Layout layout, Element parentEl)
1735        throws PortalException, SystemException {
1736
1737        Iterator itr = parentEl.elements("portlet-data").iterator();
1738
1739        while (itr.hasNext()) {
1740            Element el = (Element)itr.next();
1741
1742            String portletId = el.attributeValue("portlet-id");
1743
1744            try {
1745                PortletPreferences portletPreferences =
1746                    portletPreferencesPersistence.findByO_O_P_P(
1747                        PortletKeys.PREFS_OWNER_ID_DEFAULT,
1748                        PortletKeys.PREFS_OWNER_TYPE_LAYOUT, layout.getPlid(),
1749                        portletId);
1750
1751                String preferences = deletePortletData(
1752                    context, portletId, portletPreferences, el);
1753
1754                if (preferences != null) {
1755                    portletPreferences.setPreferences(preferences);
1756
1757                    portletPreferencesPersistence.update(portletPreferences);
1758                }
1759            }
1760            catch (NoSuchPortletPreferencesException nsppe) {
1761            }
1762        }
1763    }
1764
1765    protected String deletePortletData(
1766            PortletDataContext context, String portletId,
1767            PortletPreferences portletPreferences, Element parentEl)
1768        throws PortalException, SystemException {
1769
1770        Portlet portlet = portletLocalService.getPortletById(
1771            context.getCompanyId(), portletId);
1772
1773        if (portlet == null) {
1774            if (_log.isDebugEnabled()) {
1775                _log.debug(
1776                    "Do not delete portlet data for " + portletId +
1777                        " because the portlet does not exist");
1778            }
1779
1780            return null;
1781        }
1782
1783        PortletDataHandler portletDataHandler =
1784            portlet.getPortletDataHandlerInstance();
1785
1786        if (portletDataHandler == null) {
1787            if (_log.isDebugEnabled()) {
1788                _log.debug(
1789                    "Do not delete portlet data for " + portletId +
1790                        " because the portlet does not have a " +
1791                            "PortletDataHandler");
1792            }
1793
1794            return null;
1795        }
1796
1797        if (_log.isDebugEnabled()) {
1798            _log.debug("Deleting data for " + portletId);
1799        }
1800
1801        PortletPreferencesImpl prefsImpl =
1802            (PortletPreferencesImpl)PortletPreferencesSerializer.fromDefaultXML(
1803                portletPreferences.getPreferences());
1804
1805        prefsImpl = (PortletPreferencesImpl)portletDataHandler.deleteData(
1806            context, portletId, prefsImpl);
1807
1808        if (prefsImpl == null) {
1809            return null;
1810        }
1811
1812        return PortletPreferencesSerializer.toXML(prefsImpl);
1813    }
1814
1815    protected void exportComments(PortletDataContext context, Element root)
1816        throws SystemException {
1817
1818        try {
1819            XStream xStream = new XStream();
1820
1821            Map commentsMap = context.getComments();
1822
1823            Iterator itr = commentsMap.keySet().iterator();
1824
1825            while (itr.hasNext()) {
1826                String key = (String)itr.next();
1827
1828                String[] comment = key.split(StringPool.POUND);
1829
1830                Element el = root.addElement("comments");
1831
1832                el.addAttribute("class-name", comment[0]);
1833                el.addAttribute("class-pk", comment[1]);
1834
1835                List messages = (List)commentsMap.get(key);
1836
1837                String xml = xStream.toXML(messages);
1838
1839                Document tempDoc = PortalUtil.readDocumentFromXML(xml);
1840
1841                el.content().add(tempDoc.getRootElement().createCopy());
1842            }
1843        }
1844        catch (Exception e) {
1845            throw new SystemException(e);
1846        }
1847    }
1848
1849    protected Element exportGroupPermissions(
1850            long companyId, long groupId, String resourceName,
1851            String resourcePrimKey, Element parentEl, String elName)
1852        throws PortalException, SystemException {
1853
1854        Element el = parentEl.addElement(elName);
1855
1856        List permissions = permissionLocalService.getGroupPermissions(
1857            groupId, companyId, resourceName, ResourceImpl.SCOPE_INDIVIDUAL,
1858            resourcePrimKey);
1859
1860        List actions = ResourceActionsUtil.getActions(permissions);
1861
1862        for (int i = 0; i < actions.size(); i++) {
1863            String action = (String)actions.get(i);
1864
1865            Element actionKeyEl = el.addElement("action-key");
1866
1867            actionKeyEl.addText(action);
1868        }
1869
1870        return el;
1871    }
1872
1873    protected void exportGroupRoles(
1874            LayoutCache layoutCache, long companyId, long groupId,
1875            String resourceName, String entityName, Element parentEl)
1876        throws PortalException, SystemException {
1877
1878        List roles = layoutCache.getGroupRoles(groupId);
1879
1880        Element groupEl = exportRoles(
1881            companyId, resourceName, ResourceImpl.SCOPE_GROUP,
1882            String.valueOf(groupId), parentEl, entityName + "-roles", roles);
1883
1884        if (groupEl.elements().isEmpty()) {
1885            parentEl.remove(groupEl);
1886        }
1887    }
1888
1889    protected void exportInheritedPermissions(
1890            LayoutCache layoutCache, long companyId, String resourceName,
1891            String resourcePrimKey, Element parentEl, String entityName)
1892        throws PortalException, SystemException {
1893
1894        Element entityPermissionsEl = DocumentHelper.createElement(
1895            entityName + "-permissions");
1896
1897        Map entityMap = layoutCache.getEntityMap(companyId, entityName);
1898
1899        Iterator itr = entityMap.entrySet().iterator();
1900
1901        while (itr.hasNext()) {
1902            Map.Entry entry = (Map.Entry)itr.next();
1903
1904            String name = entry.getKey().toString();
1905
1906            long entityGroupId = ((Long)entry.getValue()).longValue();
1907
1908            Element entityEl = exportGroupPermissions(
1909                companyId, entityGroupId, resourceName, resourcePrimKey,
1910                entityPermissionsEl, entityName + "-actions");
1911
1912            if (entityEl.elements().isEmpty()) {
1913                entityPermissionsEl.remove(entityEl);
1914            }
1915            else {
1916                entityEl.addAttribute("name", name);
1917            }
1918        }
1919
1920        if (!entityPermissionsEl.elements().isEmpty()) {
1921            parentEl.add(entityPermissionsEl);
1922        }
1923    }
1924
1925    protected void exportInheritedRoles(
1926            LayoutCache layoutCache, long companyId, long groupId,
1927            String resourceName, String entityName, Element parentEl)
1928        throws PortalException, SystemException {
1929
1930        Element entityRolesEl = DocumentHelper.createElement(
1931            entityName + "-roles");
1932
1933        Map entityMap = layoutCache.getEntityMap(companyId, entityName);
1934
1935        Iterator itr = entityMap.entrySet().iterator();
1936
1937        while (itr.hasNext()) {
1938            Map.Entry entry = (Map.Entry)itr.next();
1939
1940            String name = entry.getKey().toString();
1941
1942            long entityGroupId = ((Long)entry.getValue()).longValue();
1943
1944            List entityRoles = layoutCache.getGroupRoles(entityGroupId);
1945
1946            Element entityEl = exportRoles(
1947                companyId, resourceName, ResourceImpl.SCOPE_GROUP,
1948                String.valueOf(groupId), entityRolesEl, entityName,
1949                entityRoles);
1950
1951            if (entityEl.elements().isEmpty()) {
1952                entityRolesEl.remove(entityEl);
1953            }
1954            else {
1955                entityEl.addAttribute("name", name);
1956            }
1957        }
1958
1959        if (!entityRolesEl.elements().isEmpty()) {
1960            parentEl.add(entityRolesEl);
1961        }
1962    }
1963
1964    protected void exportLayoutPermissions(
1965            LayoutCache layoutCache, long companyId, long groupId,
1966            Group guestGroup, Layout layout, Element permissionsEl,
1967            boolean exportUserPermissions)
1968        throws PortalException, SystemException {
1969
1970        String resourceName = Layout.class.getName();
1971        String resourcePrimKey = String.valueOf(layout.getPlid());
1972
1973        exportGroupPermissions(
1974            companyId, groupId, resourceName, resourcePrimKey, permissionsEl,
1975            "community-actions");
1976
1977        if (groupId != guestGroup.getGroupId()) {
1978            exportGroupPermissions(
1979                companyId, guestGroup.getGroupId(), resourceName,
1980                resourcePrimKey, permissionsEl, "guest-actions");
1981        }
1982
1983        if (exportUserPermissions) {
1984            exportUserPermissions(
1985                layoutCache, companyId, groupId, resourceName, resourcePrimKey,
1986                permissionsEl);
1987        }
1988
1989        exportInheritedPermissions(
1990            layoutCache, companyId, resourceName, resourcePrimKey,
1991            permissionsEl, "organization");
1992
1993        exportInheritedPermissions(
1994            layoutCache, companyId, resourceName, resourcePrimKey,
1995            permissionsEl, "location");
1996
1997        exportInheritedPermissions(
1998            layoutCache, companyId, resourceName, resourcePrimKey,
1999            permissionsEl, "user-group");
2000    }
2001
2002    protected void exportLayoutRoles(
2003            LayoutCache layoutCache, long companyId, long groupId,
2004            Element rolesEl)
2005        throws PortalException, SystemException {
2006
2007        String resourceName = Layout.class.getName();
2008
2009        exportGroupRoles(
2010            layoutCache, companyId, groupId, resourceName, "community",
2011            rolesEl);
2012
2013        exportUserRoles(layoutCache, companyId, groupId, resourceName, rolesEl);
2014
2015        exportInheritedRoles(
2016            layoutCache, companyId, groupId, resourceName, "organization",
2017            rolesEl);
2018
2019        exportInheritedRoles(
2020            layoutCache, companyId, groupId, resourceName, "location", rolesEl);
2021
2022        exportInheritedRoles(
2023            layoutCache, companyId, groupId, resourceName, "user-group",
2024            rolesEl);
2025    }
2026
2027    protected void exportPortletData(
2028            PortletDataContext context, Layout layout,
2029            LayoutTypePortlet layoutTypePortlet, Element parentEl)
2030        throws PortalException, SystemException {
2031
2032        Iterator itr = portletPreferencesLocalService.getPortletPreferences(
2033            layout.getPlid()).iterator();
2034
2035        while (itr.hasNext()) {
2036            PortletPreferences portletPreferences =
2037                (PortletPreferences)itr.next();
2038
2039            javax.portlet.PortletPreferences jxPrefs =
2040                portletPreferencesLocalService.getPreferences(
2041                    layout.getCompanyId(), portletPreferences.getOwnerId(),
2042                    portletPreferences.getOwnerType(),
2043                    portletPreferences.getPlid(),
2044                    portletPreferences.getPortletId());
2045
2046            String portletId = portletPreferences.getPortletId();
2047
2048            if (layoutTypePortlet.hasPortletId(portletId)) {
2049                exportPortletData(context, portletId, jxPrefs, parentEl);
2050            }
2051        }
2052    }
2053
2054    protected void exportPortletData(
2055            PortletDataContext context, String portletId,
2056            javax.portlet.PortletPreferences portletPreferences,
2057            Element parentEl)
2058        throws PortalException, SystemException {
2059
2060        Portlet portlet = portletLocalService.getPortletById(
2061            context.getCompanyId(), portletId);
2062
2063        if (portlet == null) {
2064            if (_log.isDebugEnabled()) {
2065                _log.debug(
2066                    "Do not export portlet data for " + portletId +
2067                        " because the portlet does not exist");
2068            }
2069
2070            return;
2071        }
2072
2073        PortletDataHandler portletDataHandler =
2074            portlet.getPortletDataHandlerInstance();
2075
2076        if (portletDataHandler == null) {
2077            return;
2078        }
2079
2080        if (_log.isDebugEnabled()) {
2081            _log.debug("Exporting data for " + portletId);
2082        }
2083
2084        Map parameterMap = context.getParameterMap();
2085
2086        boolean exportData = false;
2087
2088        if (MapUtil.getBoolean(
2089                parameterMap,
2090                PortletDataHandlerKeys.PORTLET_DATA + "_" + portletId) ||
2091            MapUtil.getBoolean(
2092                parameterMap, PortletDataHandlerKeys.PORTLET_DATA_ALL)) {
2093
2094            exportData = true;
2095        }
2096
2097        if (!exportData) {
2098            if (_log.isDebugEnabled()) {
2099                _log.debug(
2100                    "Not exporting data for " + portletId +
2101                        " because it was not selected by the user");
2102            }
2103
2104            return;
2105        }
2106
2107        String data = portletDataHandler.exportData(
2108            context, portletId, portletPreferences);
2109
2110        if (data == null) {
2111            if (_log.isDebugEnabled()) {
2112                _log.debug(
2113                    "Not exporting data for " + portletId +
2114                        " because null data was returned");
2115            }
2116
2117            return;
2118        }
2119
2120        Element el = parentEl.addElement("portlet-data");
2121
2122        el.addAttribute("portlet-id", portletId);
2123        el.addCDATA(data);
2124    }
2125
2126    protected void exportPortletPermissions(
2127            LayoutCache layoutCache, long companyId, long groupId,
2128            Group guestGroup, Layout layout,
2129            LayoutTypePortlet layoutTypePortlet, Set portletIds,
2130            Element permissionsEl, boolean exportUserPermissions)
2131        throws PortalException, SystemException {
2132
2133        Iterator itr = layoutTypePortlet.getPortletIds().iterator();
2134
2135        while (itr.hasNext()) {
2136            String portletId = (String)itr.next();
2137
2138            if (!portletIds.contains(portletId)) {
2139                portletIds.add(portletId);
2140            }
2141
2142            if (layoutTypePortlet.hasPortletId(portletId)) {
2143                String resourceName = PortletImpl.getRootPortletId(portletId);
2144                String resourcePrimKey = PortletPermissionUtil.getPrimaryKey(
2145                    layout.getPlid(), portletId);
2146
2147                Element portletEl = permissionsEl.addElement("portlet");
2148
2149                portletEl.addAttribute("portlet-id", portletId);
2150
2151                exportGroupPermissions(
2152                    companyId, groupId, resourceName, resourcePrimKey,
2153                    portletEl, "community-actions");
2154
2155                if (groupId != guestGroup.getGroupId()) {
2156                    exportGroupPermissions(
2157                        companyId, guestGroup.getGroupId(), resourceName,
2158                        resourcePrimKey, portletEl, "guest-actions");
2159                }
2160
2161                if (exportUserPermissions) {
2162                    exportUserPermissions(
2163                        layoutCache, companyId, groupId, resourceName,
2164                        resourcePrimKey, portletEl);
2165                }
2166
2167                exportInheritedPermissions(
2168                    layoutCache, companyId, resourceName, resourcePrimKey,
2169                    portletEl, "organization");
2170
2171                exportInheritedPermissions(
2172                    layoutCache, companyId, resourceName, resourcePrimKey,
2173                    portletEl, "location");
2174
2175                exportInheritedPermissions(
2176                    layoutCache, companyId, resourceName, resourcePrimKey,
2177                    portletEl, "user-group");
2178            }
2179        }
2180    }
2181
2182    protected void exportPortletPreferences(
2183            long ownerId, int ownerType, long plid, boolean defaultUser,
2184            Element parentEl)
2185        throws PortalException, SystemException {
2186
2187        exportPortletPreferences(
2188            ownerId, ownerType, defaultUser, plid, null, parentEl);
2189    }
2190
2191    protected void exportPortletPreferences(
2192            long ownerId, int ownerType, boolean defaultUser, long plid,
2193            LayoutTypePortlet layoutTypePortlet, Element parentEl)
2194        throws PortalException, SystemException {
2195
2196        Iterator itr = portletPreferencesLocalService.getPortletPreferences(
2197            ownerId, ownerType, plid).iterator();
2198
2199        while (itr.hasNext()) {
2200            PortletPreferences portletPreferences =
2201                (PortletPreferences)itr.next();
2202
2203            String portletId = portletPreferences.getPortletId();
2204
2205            if ((layoutTypePortlet == null) ||
2206                (layoutTypePortlet.hasPortletId(portletId))) {
2207
2208                Element el = parentEl.addElement("portlet-preferences");
2209
2210                el.addAttribute("owner-id", String.valueOf(ownerId));
2211                el.addAttribute("owner-type", String.valueOf(ownerType));
2212                el.addAttribute("default-user", String.valueOf(defaultUser));
2213                el.addAttribute("plid", String.valueOf(plid));
2214                el.addAttribute("portlet-id", portletId);
2215                el.addElement("preferences").addCDATA(
2216                    portletPreferences.getPreferences());
2217            }
2218        }
2219    }
2220
2221    protected void exportPortletPreferences(
2222            long ownerId, int ownerType, boolean defaultUser, Layout layout,
2223            String portletId, Element parentEl)
2224        throws PortalException, SystemException {
2225
2226        PortletPreferences portletPreferences = null;
2227
2228        long plid = layout.getPlid();
2229
2230        if ((ownerType == PortletKeys.PREFS_OWNER_TYPE_COMPANY) ||
2231            (ownerType == PortletKeys.PREFS_OWNER_TYPE_GROUP)) {
2232
2233            plid = PortletKeys.PREFS_OWNER_ID_DEFAULT;
2234        }
2235
2236        try {
2237            portletPreferences =
2238                portletPreferencesLocalService.getPortletPreferences(
2239                    ownerId, ownerType, plid, portletId);
2240
2241            LayoutTypePortlet layoutTypePortlet =
2242                (LayoutTypePortlet)layout.getLayoutType();
2243
2244            if ((layoutTypePortlet == null) ||
2245                (layoutTypePortlet.hasPortletId(portletId))) {
2246
2247                Element el = parentEl.addElement("portlet-preferences");
2248
2249                el.addAttribute("owner-id", String.valueOf(ownerId));
2250                el.addAttribute("owner-type", String.valueOf(ownerType));
2251                el.addAttribute("default-user", String.valueOf(defaultUser));
2252                el.addAttribute("plid", String.valueOf(plid));
2253                el.addAttribute("portlet-id", portletId);
2254                el.addElement("preferences").addCDATA(
2255                    portletPreferences.getPreferences());
2256            }
2257        }
2258        catch (NoSuchPortletPreferencesException nsppe) {
2259        }
2260    }
2261
2262    protected void exportPortletRoles(
2263            LayoutCache layoutCache, long companyId, long groupId,
2264            Set portletIds, Element rolesEl)
2265        throws PortalException, SystemException {
2266
2267        Iterator itr = portletIds.iterator();
2268
2269        while (itr.hasNext()) {
2270            String portletId = (String)itr.next();
2271
2272            String resourceName = PortletImpl.getRootPortletId(portletId);
2273
2274            Element portletEl = rolesEl.addElement("portlet");
2275
2276            portletEl.addAttribute("portlet-id", portletId);
2277
2278            exportGroupRoles(
2279                layoutCache, companyId, groupId, resourceName, "community",
2280                portletEl);
2281
2282            exportUserRoles(
2283                layoutCache, companyId, groupId, resourceName, portletEl);
2284
2285            exportInheritedRoles(
2286                layoutCache, companyId, groupId, resourceName, "organization",
2287                portletEl);
2288
2289            exportInheritedRoles(
2290                layoutCache, companyId, groupId, resourceName, "location",
2291                portletEl);
2292
2293            exportInheritedRoles(
2294                layoutCache, companyId, groupId, resourceName, "user-group",
2295                portletEl);
2296
2297            if (portletEl.elements().isEmpty()) {
2298                rolesEl.remove(portletEl);
2299            }
2300        }
2301    }
2302
2303    protected Element exportRoles(
2304            long companyId, String resourceName, int scope,
2305            String resourcePrimKey, Element parentEl, String elName,
2306            List roles)
2307        throws PortalException, SystemException {
2308
2309        Element el = parentEl.addElement(elName);
2310
2311        Map resourceRoles = roleLocalService.getResourceRoles(
2312            companyId, resourceName, scope, resourcePrimKey);
2313
2314        Iterator itr = resourceRoles.entrySet().iterator();
2315
2316        while (itr.hasNext()) {
2317            Map.Entry entry = (Map.Entry)itr.next();
2318
2319            String roleName = entry.getKey().toString();
2320
2321            if (hasRole(roles, roleName)) {
2322                Element roleEl = el.addElement("role");
2323
2324                roleEl.addAttribute("name", roleName);
2325
2326                List actions = (List)entry.getValue();
2327
2328                for (int i = 0; i < actions.size(); i++) {
2329                    String action = (String)actions.get(i);
2330
2331                    Element actionKeyEl = roleEl.addElement("action-key");
2332
2333                    actionKeyEl.addText(action);
2334                    actionKeyEl.addAttribute("scope", String.valueOf(scope));
2335                }
2336            }
2337        }
2338
2339        return el;
2340    }
2341
2342    protected void exportRatings(PortletDataContext context, Element root)
2343        throws SystemException {
2344
2345        try {
2346            XStream xStream = new XStream();
2347
2348            Map ratingsEntriesMap = context.getRatingsEntries();
2349
2350            Iterator itr = ratingsEntriesMap.keySet().iterator();
2351
2352            while (itr.hasNext()) {
2353                String key = (String)itr.next();
2354
2355                String[] ratingsEntry = key.split(StringPool.POUND);
2356
2357                Element el = root.addElement("ratings");
2358
2359                el.addAttribute("class-name", ratingsEntry[0]);
2360                el.addAttribute("class-pk", ratingsEntry[1]);
2361
2362                List ratingsEntries = (List)ratingsEntriesMap.get(key);
2363
2364                String xml = xStream.toXML(ratingsEntries);
2365
2366                Document tempDoc = PortalUtil.readDocumentFromXML(xml);
2367
2368                el.content().add(tempDoc.getRootElement().createCopy());
2369            }
2370        }
2371        catch (Exception e) {
2372            throw new SystemException(e);
2373        }
2374    }
2375
2376    protected void exportTags(PortletDataContext context, Element root) {
2377        Map tagsEntries = context.getTagsEntries();
2378
2379        Iterator itr = tagsEntries.keySet().iterator();
2380
2381        while (itr.hasNext()) {
2382            String key = (String)itr.next();
2383
2384            String[] tagsEntry = key.split(StringPool.POUND);
2385
2386            Element el = root.addElement("tags");
2387
2388            el.addAttribute("class-name", tagsEntry[0]);
2389            el.addAttribute("class-pk", tagsEntry[1]);
2390            el.addAttribute(
2391                "entries",
2392                StringUtil.merge((String[])tagsEntries.get(key), ","));
2393        }
2394    }
2395
2396    protected byte[] exportTheme(LayoutSet layoutSet)
2397        throws IOException, PortalException, SystemException {
2398
2399        Theme theme = layoutSet.getTheme();
2400
2401        ZipWriter zipWriter = new ZipWriter();
2402
2403        String lookAndFeelXML = ContentUtil.get(
2404            "com/liferay/portal/dependencies/liferay-look-and-feel.xml.tmpl");
2405
2406        lookAndFeelXML = StringUtil.replace(
2407            lookAndFeelXML,
2408            new String[] {
2409                "[$TEMPLATE_EXTENSION$]", "[$VIRTUAL_PATH$]"
2410            },
2411            new String[] {
2412                theme.getTemplateExtension(), theme.getVirtualPath()
2413            }
2414        );
2415
2416        zipWriter.addEntry("liferay-look-and-feel.xml", lookAndFeelXML);
2417
2418        String servletContextName = theme.getServletContextName();
2419
2420        ServletContext ctx = VelocityContextPool.get(servletContextName);
2421
2422        if (ctx == null) {
2423            if (_log.isWarnEnabled()) {
2424                _log.warn(
2425                    "Servlet context not found for theme " +
2426                        theme.getThemeId());
2427            }
2428
2429            return null;
2430        }
2431
2432        File cssPath = null;
2433        File imagesPath = null;
2434        File javaScriptPath = null;
2435        File templatesPath = null;
2436
2437        if (!theme.isLoadFromServletContext()) {
2438            ThemeLoader themeLoader = ThemeLoaderFactory.getThemeLoader(
2439                servletContextName);
2440
2441            if (themeLoader == null) {
2442                _log.error(
2443                    servletContextName + " does not map to a theme loader");
2444            }
2445            else {
2446                String realPath =
2447                    themeLoader.getFileStorage().getPath() + "/" +
2448                        theme.getName();
2449
2450                cssPath = new File(realPath + "/css");
2451                imagesPath = new File(realPath + "/images");
2452                javaScriptPath = new File(realPath + "/javascript");
2453                templatesPath = new File(realPath + "/templates");
2454            }
2455        }
2456        else {
2457            cssPath = new File(ctx.getRealPath(theme.getCssPath()));
2458            imagesPath = new File(ctx.getRealPath(theme.getImagesPath()));
2459            javaScriptPath = new File(
2460                ctx.getRealPath(theme.getJavaScriptPath()));
2461            templatesPath = new File(ctx.getRealPath(theme.getTemplatesPath()));
2462        }
2463
2464        exportThemeFiles("css", cssPath, zipWriter);
2465        exportThemeFiles("images", imagesPath, zipWriter);
2466        exportThemeFiles("javascript", javaScriptPath, zipWriter);
2467        exportThemeFiles("templates", templatesPath, zipWriter);
2468
2469        return zipWriter.finish();
2470    }
2471
2472    protected void exportThemeFiles(String path, File dir, ZipWriter zipWriter)
2473        throws IOException {
2474
2475        if ((dir == null) || (!dir.exists())) {
2476            return;
2477        }
2478
2479        File[] files = dir.listFiles();
2480
2481        for (int i = 0; i < files.length; i++) {
2482            File file = files[i];
2483
2484            if (file.isDirectory()) {
2485                exportThemeFiles(path + "/" + file.getName(), file, zipWriter);
2486            }
2487            else {
2488                zipWriter.addEntry(
2489                    path + "/" + file.getName(), FileUtil.getBytes(file));
2490            }
2491        }
2492    }
2493
2494    protected void exportUserPermissions(
2495            LayoutCache layoutCache, long companyId, long groupId,
2496            String resourceName, String resourcePrimKey, Element parentEl)
2497        throws PortalException, SystemException {
2498
2499        StopWatch stopWatch = null;
2500
2501        if (_log.isDebugEnabled()) {
2502            stopWatch = new StopWatch();
2503
2504            stopWatch.start();
2505        }
2506
2507        Element userPermissionsEl = DocumentHelper.createElement(
2508            "user-permissions");
2509
2510        List users = layoutCache.getGroupUsers(groupId);
2511
2512        for (int i = 0; i < users.size(); i++) {
2513            User user = (User)users.get(i);
2514
2515            String emailAddress = user.getEmailAddress();
2516
2517            Element userActionsEl =
2518                DocumentHelper.createElement("user-actions");
2519
2520            List permissions = permissionLocalService.getUserPermissions(
2521                user.getUserId(), companyId, resourceName,
2522                ResourceImpl.SCOPE_INDIVIDUAL, resourcePrimKey);
2523
2524            List actions = ResourceActionsUtil.getActions(permissions);
2525
2526            for (int j = 0; j < actions.size(); j++) {
2527                String action = (String)actions.get(j);
2528
2529                Element actionKeyEl = userActionsEl.addElement("action-key");
2530
2531                actionKeyEl.addText(action);
2532            }
2533
2534            if (!userActionsEl.elements().isEmpty()) {
2535                userActionsEl.addAttribute("email-address", emailAddress);
2536                userPermissionsEl.add(userActionsEl);
2537            }
2538        }
2539
2540        if (!userPermissionsEl.elements().isEmpty()) {
2541            parentEl.add(userPermissionsEl);
2542        }
2543
2544        if (_log.isDebugEnabled()) {
2545            _log.debug(
2546                "Export user permissions for {" + resourceName + ", " +
2547                    resourcePrimKey + "} with " + users.size() +
2548                        " users takes " + stopWatch.getTime() + " ms");
2549        }
2550    }
2551
2552    protected void exportUserRoles(
2553            LayoutCache layoutCache, long companyId, long groupId,
2554            String resourceName, Element parentEl)
2555        throws PortalException, SystemException {
2556
2557        Element userRolesEl = DocumentHelper.createElement("user-roles");
2558
2559        List users = layoutCache.getGroupUsers(groupId);
2560
2561        for (int i = 0; i < users.size(); i++) {
2562            User user = (User)users.get(i);
2563
2564            long userId = user.getUserId();
2565            String emailAddress = user.getEmailAddress();
2566
2567            List userRoles = layoutCache.getUserRoles(userId);
2568
2569            Element userEl = exportRoles(
2570                companyId, resourceName, ResourceImpl.SCOPE_GROUP,
2571                String.valueOf(groupId), userRolesEl, "user", userRoles);
2572
2573            if (userEl.elements().isEmpty()) {
2574                userRolesEl.remove(userEl);
2575            }
2576            else {
2577                userEl.addAttribute("email-address", emailAddress);
2578            }
2579        }
2580
2581        if (!userRolesEl.elements().isEmpty()) {
2582            parentEl.add(userRolesEl);
2583        }
2584    }
2585
2586    protected void fixTypeSettings(Layout layout) {
2587        if (layout.getType().equals(LayoutImpl.TYPE_URL)) {
2588            Properties typeSettings = layout.getTypeSettingsProperties();
2589
2590            String url = GetterUtil.getString(typeSettings.getProperty("url"));
2591
2592            String friendlyURLPrivateGroupPath =
2593                PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_GROUP_SERVLET_MAPPING;
2594            String friendlyURLPrivateUserPath =
2595                PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING;
2596            String friendlyURLPublicPath =
2597                PropsValues.LAYOUT_FRIENDLY_URL_PUBLIC_SERVLET_MAPPING;
2598
2599            if (url.startsWith(friendlyURLPrivateGroupPath) ||
2600                url.startsWith(friendlyURLPrivateUserPath) ||
2601                url.startsWith(friendlyURLPublicPath)) {
2602
2603                int x = url.indexOf(StringPool.SLASH, 1);
2604
2605                if (x > 0) {
2606                    int y = url.indexOf(StringPool.SLASH, x + 1);
2607
2608                    if (y > x) {
2609                        String fixedUrl = url.substring(0, x) +
2610
2611                        layout.getGroup().getFriendlyURL() +
2612
2613                        url.substring(y);
2614
2615                        typeSettings.setProperty("url", fixedUrl);
2616                    }
2617                }
2618            }
2619        }
2620    }
2621
2622    protected List getActions(Element el) {
2623        List actions = new ArrayList();
2624
2625        Iterator itr = el.elements("action-key").iterator();
2626
2627        while (itr.hasNext()) {
2628            Element actionEl = (Element)itr.next();
2629
2630            actions.add(actionEl.getText());
2631        }
2632
2633        return actions;
2634    }
2635
2636    protected String getFriendlyURL(String friendlyURL) {
2637        return Normalizer.normalizeToAscii(friendlyURL.trim().toLowerCase());
2638    }
2639
2640    protected long getNextLayoutId(long groupId, boolean privateLayout)
2641        throws SystemException {
2642
2643        long layoutId = 0;
2644
2645        List layouts = layoutPersistence.findByG_P(groupId, privateLayout);
2646
2647        for (int i = 0; i < layouts.size(); i++) {
2648            Layout curLayout = (Layout)layouts.get(i);
2649
2650            long curLayoutId = curLayout.getLayoutId();
2651
2652            if (curLayoutId > layoutId) {
2653                layoutId = curLayoutId;
2654            }
2655        }
2656
2657        return ++layoutId;
2658    }
2659
2660    protected int getNextPriority(
2661            long groupId, boolean privateLayout, long parentLayoutId)
2662        throws SystemException {
2663
2664        List layouts = layoutPersistence.findByG_P_P(
2665            groupId, privateLayout, parentLayoutId);
2666
2667        if (layouts.size() == 0) {
2668            return 0;
2669        }
2670
2671        Layout layout = (Layout)layouts.get(layouts.size() - 1);
2672
2673        return layout.getPriority() + 1;
2674    }
2675
2676    protected long getParentLayoutId(
2677            long groupId, boolean privateLayout, long parentLayoutId)
2678        throws PortalException, SystemException {
2679
2680        if (parentLayoutId != LayoutImpl.DEFAULT_PARENT_LAYOUT_ID) {
2681
2682            // Ensure parent layout exists
2683
2684            try {
2685                layoutPersistence.findByG_P_L(
2686                    groupId, privateLayout, parentLayoutId);
2687            }
2688            catch (NoSuchLayoutException nsfe) {
2689                parentLayoutId = LayoutImpl.DEFAULT_PARENT_LAYOUT_ID;
2690            }
2691        }
2692
2693        return parentLayoutId;
2694    }
2695
2696    protected boolean hasRole(List roles, String roleName) {
2697        if ((roles == null) || (roles.size() == 0)) {
2698            return false;
2699        }
2700
2701        for (int i = 0; i < roles.size(); i++) {
2702            Role role = (Role)roles.get(i);
2703
2704            if (role.getName().equals(roleName)) {
2705                return true;
2706            }
2707        }
2708
2709        return false;
2710    }
2711
2712    protected void importGroupPermissions(
2713            LayoutCache layoutCache, long companyId, long groupId,
2714            String resourceName, String resourcePrimKey, Element parentEl,
2715            String elName, boolean portletActions)
2716        throws PortalException, SystemException {
2717
2718        Element actionEl = parentEl.element(elName);
2719
2720        if (actionEl == null) {
2721            return;
2722        }
2723
2724        List actions = getActions(actionEl);
2725
2726        Resource resource = layoutCache.getResource(
2727            companyId, groupId, resourceName, ResourceImpl.SCOPE_INDIVIDUAL,
2728            resourcePrimKey, portletActions);
2729
2730        permissionLocalService.setGroupPermissions(
2731            groupId, (String[])actions.toArray(new String[0]),
2732            resource.getResourceId());
2733    }
2734
2735    protected void importGroupRoles(
2736            LayoutCache layoutCache, long companyId, long groupId,
2737            String resourceName, String entityName,
2738            Element parentEl)
2739        throws PortalException, SystemException {
2740
2741        Element entityRolesEl = parentEl.element(entityName + "-roles");
2742
2743        if (entityRolesEl == null) {
2744            return;
2745        }
2746
2747        importRolePermissions(
2748            layoutCache, companyId, resourceName, ResourceImpl.SCOPE_GROUP,
2749            String.valueOf(groupId), entityRolesEl, true);
2750    }
2751
2752    protected void importInheritedPermissions(
2753            LayoutCache layoutCache, long companyId, String resourceName,
2754            String resourcePrimKey, Element permissionsEl, String entityName,
2755            boolean portletActions)
2756        throws PortalException, SystemException {
2757
2758        Element entityPermissionsEl = permissionsEl.element(
2759            entityName + "-permissions");
2760
2761        if (entityPermissionsEl == null) {
2762            return;
2763        }
2764
2765        List actionsEls = entityPermissionsEl.elements(
2766            entityName + "-actions");
2767
2768        for (int i = 0; i < actionsEls.size(); i++) {
2769            Element actionEl = (Element)actionsEls.get(i);
2770
2771            String name = actionEl.attributeValue("name");
2772
2773            long entityGroupId = layoutCache.getEntityGroupId(
2774                companyId, entityName, name);
2775
2776            if (entityGroupId == 0) {
2777                _log.warn(
2778                    "Ignore inherited permissions for entity " + entityName +
2779                        " with name " + name);
2780            }
2781            else {
2782                Element parentEl = DocumentHelper.createElement("parent");
2783
2784                parentEl.add(actionEl.createCopy());
2785
2786                importGroupPermissions(
2787                    layoutCache, companyId, entityGroupId, resourceName,
2788                    resourcePrimKey, parentEl, entityName + "-actions",
2789                    portletActions);
2790            }
2791        }
2792    }
2793
2794    protected void importInheritedRoles(
2795            LayoutCache layoutCache, long companyId, long groupId,
2796            String resourceName, String entityName, Element parentEl)
2797        throws PortalException, SystemException {
2798
2799        Element entityRolesEl = parentEl.element(entityName + "-roles");
2800
2801        if (entityRolesEl == null) {
2802            return;
2803        }
2804
2805        List entityEls = entityRolesEl.elements(entityName);
2806
2807        for (int i = 0; i < entityEls.size(); i++) {
2808            Element entityEl = (Element)entityEls.get(i);
2809
2810            String name = entityEl.attributeValue("name");
2811
2812            long entityGroupId = layoutCache.getEntityGroupId(
2813                companyId, entityName, name);
2814
2815            if (entityGroupId == 0) {
2816                _log.warn(
2817                    "Ignore inherited roles for entity " + entityName +
2818                        " with name " + name);
2819            }
2820            else {
2821                importRolePermissions(
2822                    layoutCache, companyId, resourceName,
2823                    ResourceImpl.SCOPE_GROUP, String.valueOf(groupId), entityEl,
2824                    false);
2825            }
2826        }
2827    }
2828
2829    protected void importLayoutPermissions(
2830            LayoutCache layoutCache, long companyId, long groupId,
2831            Group guestGroup, Layout layout, Element permissionsEl,
2832            boolean importUserPermissions)
2833        throws PortalException, SystemException {
2834
2835        String resourceName = Layout.class.getName();
2836        String resourcePrimKey = String.valueOf(layout.getPlid());
2837
2838        importGroupPermissions(
2839            layoutCache, companyId, groupId, resourceName, resourcePrimKey,
2840            permissionsEl, "community-actions", false);
2841
2842        if (groupId != guestGroup.getGroupId()) {
2843            importGroupPermissions(
2844                layoutCache, companyId, guestGroup.getGroupId(), resourceName,
2845                resourcePrimKey, permissionsEl, "guest-actions", false);
2846        }
2847
2848        if (importUserPermissions) {
2849            importUserPermissions(
2850                layoutCache, companyId, groupId, resourceName, resourcePrimKey,
2851                permissionsEl, false);
2852        }
2853
2854        importInheritedPermissions(
2855            layoutCache, companyId, resourceName, resourcePrimKey,
2856            permissionsEl, "organization", false);
2857
2858        importInheritedPermissions(
2859            layoutCache, companyId, resourceName, resourcePrimKey,
2860            permissionsEl, "location", false);
2861
2862        importInheritedPermissions(
2863            layoutCache, companyId, resourceName, resourcePrimKey,
2864            permissionsEl, "user-group", false);
2865    }
2866
2867    protected void importLayoutRoles(
2868            LayoutCache layoutCache, long companyId, long groupId,
2869            Element rolesEl)
2870        throws PortalException, SystemException {
2871
2872        String resourceName = Layout.class.getName();
2873
2874        importGroupRoles(
2875            layoutCache, companyId, groupId, resourceName, "community",
2876            rolesEl);
2877
2878        importUserRoles(layoutCache, companyId, groupId, resourceName, rolesEl);
2879
2880        importInheritedRoles(
2881            layoutCache, companyId, groupId, resourceName, "organization",
2882            rolesEl);
2883
2884        importInheritedRoles(
2885            layoutCache, companyId, groupId, resourceName, "location", rolesEl);
2886
2887        importInheritedRoles(
2888            layoutCache, companyId, groupId, resourceName, "user-group",
2889            rolesEl);
2890    }
2891
2892    protected void importPortletData(
2893            PortletDataContext context, Layout layout, Element parentEl)
2894        throws PortalException, SystemException {
2895
2896        Iterator itr = parentEl.elements("portlet-data").iterator();
2897
2898        while (itr.hasNext()) {
2899            Element el = (Element)itr.next();
2900
2901            String portletId = el.attributeValue("portlet-id");
2902
2903            try {
2904                PortletPreferences portletPreferences =
2905                    portletPreferencesPersistence.findByO_O_P_P(
2906                        PortletKeys.PREFS_OWNER_ID_DEFAULT,
2907                        PortletKeys.PREFS_OWNER_TYPE_LAYOUT, layout.getPlid(),
2908                        portletId);
2909
2910                String preferences = importPortletData(
2911                    context, portletId, portletPreferences, el);
2912
2913                if (preferences != null) {
2914                    portletPreferences.setPreferences(preferences);
2915
2916                    portletPreferencesPersistence.update(portletPreferences);
2917                }
2918            }
2919            catch (NoSuchPortletPreferencesException nsppe) {
2920            }
2921        }
2922    }
2923
2924    protected String importPortletData(
2925            PortletDataContext context, String portletId,
2926            PortletPreferences portletPreferences, Element parentEl)
2927        throws PortalException, SystemException {
2928
2929        Portlet portlet = portletLocalService.getPortletById(
2930            context.getCompanyId(), portletId);
2931
2932        if (portlet == null) {
2933            if (_log.isDebugEnabled()) {
2934                _log.debug(
2935                    "Do not import portlet data for " + portletId +
2936                        " because the portlet does not exist");
2937            }
2938
2939            return null;
2940        }
2941
2942        PortletDataHandler portletDataHandler =
2943            portlet.getPortletDataHandlerInstance();
2944
2945        if (portletDataHandler == null) {
2946            if (_log.isDebugEnabled()) {
2947                _log.debug(
2948                    "Do not import portlet data for " + portletId +
2949                        " because the portlet does not have a " +
2950                            "PortletDataHandler");
2951            }
2952
2953            return null;
2954        }
2955
2956        if (_log.isDebugEnabled()) {
2957            _log.debug("Importing data for " + portletId);
2958        }
2959
2960        PortletPreferencesImpl prefsImpl =
2961            (PortletPreferencesImpl)PortletPreferencesSerializer.fromDefaultXML(
2962                portletPreferences.getPreferences());
2963
2964        prefsImpl = (PortletPreferencesImpl)portletDataHandler.importData(
2965            context, portletId, prefsImpl, parentEl.getText());
2966
2967        if (prefsImpl == null) {
2968            return null;
2969        }
2970
2971        return PortletPreferencesSerializer.toXML(prefsImpl);
2972    }
2973
2974    protected void importPortletPermissions(
2975            LayoutCache layoutCache, long companyId, long groupId,
2976            Group guestGroup, Layout layout, Element permissionsEl,
2977            boolean importUserPermissions)
2978        throws PortalException, SystemException {
2979
2980        Iterator itr = permissionsEl.elements("portlet").iterator();
2981
2982        while (itr.hasNext()) {
2983            Element portletEl = (Element)itr.next();
2984
2985            String portletId = portletEl.attributeValue("portlet-id");
2986
2987            String resourceName = PortletImpl.getRootPortletId(portletId);
2988            String resourcePrimKey = PortletPermissionUtil.getPrimaryKey(
2989                layout.getPlid(), portletId);
2990
2991            Portlet portlet = portletLocalService.getPortletById(
2992                companyId, resourceName);
2993
2994            if (portlet == null) {
2995                if (_log.isDebugEnabled()) {
2996                    _log.debug(
2997                        "Do not import portlet permissions for " + portletId +
2998                            " because the portlet does not exist");
2999                }
3000            }
3001            else {
3002                importGroupPermissions(
3003                    layoutCache, companyId, groupId, resourceName,
3004                    resourcePrimKey, portletEl, "community-actions", true);
3005
3006                if (groupId != guestGroup.getGroupId()) {
3007                    importGroupPermissions(
3008                        layoutCache, companyId, guestGroup.getGroupId(),
3009                        resourceName, resourcePrimKey, portletEl,
3010                        "guest-actions", true);
3011                }
3012
3013                if (importUserPermissions) {
3014                    importUserPermissions(
3015                        layoutCache, companyId, groupId, resourceName,
3016                        resourcePrimKey, portletEl, true);
3017                }
3018
3019                importInheritedPermissions(
3020                    layoutCache, companyId, resourceName, resourcePrimKey,
3021                    portletEl, "organization", true);
3022
3023                importInheritedPermissions(
3024                    layoutCache, companyId, resourceName, resourcePrimKey,
3025                    portletEl, "location", true);
3026
3027                importInheritedPermissions(
3028                    layoutCache, companyId, resourceName, resourcePrimKey,
3029                    portletEl, "user-group", true);
3030            }
3031        }
3032    }
3033
3034    protected void importPortletPreferences(
3035            long companyId, long plid, Element parentEl,
3036            boolean importPortletSetup, boolean importUserPreferences)
3037        throws PortalException, SystemException {
3038
3039        long defaultUserId = userLocalService.getDefaultUserId(companyId);
3040
3041        Iterator itr = parentEl.elements("portlet-preferences").iterator();
3042
3043        while (itr.hasNext()) {
3044            Element el = (Element)itr.next();
3045
3046            long ownerId = GetterUtil.getLong(el.attributeValue("owner-id"));
3047            int ownerType = GetterUtil.getInteger(
3048                el.attributeValue("owner-type"));
3049
3050            if (ownerType == PortletKeys.PREFS_OWNER_TYPE_COMPANY) {
3051                continue;
3052            }
3053
3054            if ((ownerType != PortletKeys.PREFS_OWNER_TYPE_USER) &&
3055                !importPortletSetup) {
3056
3057                continue;
3058            }
3059
3060            if ((ownerType == PortletKeys.PREFS_OWNER_TYPE_USER) &&
3061                (ownerId != PortletKeys.PREFS_OWNER_ID_DEFAULT) &&
3062                !importUserPreferences) {
3063
3064                continue;
3065            }
3066
3067            if (ownerType == PortletKeys.PREFS_OWNER_TYPE_GROUP) {
3068                plid = PortletKeys.PREFS_PLID_SHARED;
3069            }
3070
3071            boolean defaultUser = GetterUtil.getBoolean(
3072                el.attributeValue("default-user"));
3073            String portletId = el.attributeValue("portlet-id");
3074            String preferences = el.elementText("preferences");
3075
3076            if (defaultUser) {
3077                ownerId = defaultUserId;
3078            }
3079
3080            try {
3081                portletPreferencesLocalService.deletePortletPreferences(
3082                    ownerId, ownerType, plid, portletId);
3083            }
3084            catch (NoSuchPortletPreferencesException nsppe) {
3085            }
3086
3087            long portletPreferencesId = counterLocalService.increment();
3088
3089            PortletPreferences portletPreferences =
3090                portletPreferencesPersistence.create(portletPreferencesId);
3091
3092            portletPreferences.setOwnerId(ownerId);
3093            portletPreferences.setOwnerType(ownerType);
3094            portletPreferences.setPlid(plid);
3095            portletPreferences.setPortletId(portletId);
3096
3097            portletPreferences.setPreferences(preferences);
3098
3099            portletPreferencesPersistence.update(portletPreferences);
3100        }
3101    }
3102
3103    protected void importPortletRoles(
3104            LayoutCache layoutCache, long companyId, long groupId,
3105            Element rolesEl)
3106        throws PortalException, SystemException {
3107
3108        Iterator itr = rolesEl.elements("portlet").iterator();
3109
3110        while (itr.hasNext()) {
3111            Element portletEl = (Element)itr.next();
3112
3113            String portletId = portletEl.attributeValue("portlet-id");
3114
3115            String resourceName = PortletImpl.getRootPortletId(portletId);
3116
3117            Portlet portlet = portletLocalService.getPortletById(
3118                companyId, resourceName);
3119
3120            if (portlet == null) {
3121                if (_log.isDebugEnabled()) {
3122                    _log.debug(
3123                        "Do not import portlet roles for " + portletId +
3124                            " because the portlet does not exist");
3125                }
3126            }
3127            else {
3128                importGroupRoles(
3129                    layoutCache, companyId, groupId, resourceName, "community",
3130                    portletEl);
3131
3132                importUserRoles(
3133                    layoutCache, companyId, groupId, resourceName, portletEl);
3134
3135                importInheritedRoles(
3136                    layoutCache, companyId, groupId, resourceName,
3137                    "organization", portletEl);
3138
3139                importInheritedRoles(
3140                    layoutCache, companyId, groupId, resourceName, "location",
3141                    portletEl);
3142
3143                importInheritedRoles(
3144                    layoutCache, companyId, groupId, resourceName, "user-group",
3145                    portletEl);
3146            }
3147        }
3148    }
3149
3150    protected void importRolePermissions(
3151            LayoutCache layoutCache, long companyId, String resourceName,
3152            int scope, String resourcePrimKey, Element parentEl,
3153            boolean communityRole)
3154        throws PortalException, SystemException {
3155
3156        List roleEls = parentEl.elements("role");
3157
3158        for (int i = 0; i < roleEls.size(); i++) {
3159            Element roleEl = (Element)roleEls.get(i);
3160
3161            String roleName = roleEl.attributeValue("name");
3162
3163            Role role = layoutCache.getRole(companyId, roleName);
3164
3165            if (role == null) {
3166                _log.warn(
3167                    "Ignoring permissions for role with name " + roleName);
3168            }
3169            else {
3170                List actions = getActions(roleEl);
3171
3172                permissionLocalService.setRolePermissions(
3173                    role.getRoleId(), companyId, resourceName, scope,
3174                    resourcePrimKey, (String[])actions.toArray(new String[0]));
3175
3176                if (communityRole) {
3177                    long[] groupIds = {GetterUtil.getLong(resourcePrimKey)};
3178
3179                    groupLocalService.addRoleGroups(role.getRoleId(), groupIds);
3180                }
3181            }
3182        }
3183    }
3184
3185    protected String importTheme(LayoutSet layoutSet, byte[] themeZip)
3186        throws IOException {
3187
3188        ThemeLoader themeLoader = ThemeLoaderFactory.getDefaultThemeLoader();
3189
3190        if (themeLoader == null) {
3191            _log.error("No theme loaders are deployed");
3192
3193            return null;
3194        }
3195
3196        ZipReader zipReader = new ZipReader(new ByteArrayInputStream(themeZip));
3197
3198        Map entries = zipReader.getEntries();
3199
3200        String lookAndFeelXML = new String(
3201            (byte[])entries.get("liferay-look-and-feel.xml"));
3202
3203        String themeId = String.valueOf(layoutSet.getGroupId());
3204
3205        if (layoutSet.isPrivateLayout()) {
3206            themeId += "-private";
3207        }
3208        else {
3209            themeId += "-public";
3210        }
3211
3212        if (PropsValues.THEME_LOADER_NEW_THEME_ID_ON_IMPORT) {
3213            Date now = new Date();
3214
3215            themeId += "-" + Time.getShortTimestamp(now);
3216        }
3217
3218        String themeName = themeId;
3219
3220        lookAndFeelXML = StringUtil.replace(
3221            lookAndFeelXML,
3222            new String[] {
3223                "[$GROUP_ID$]", "[$THEME_ID$]", "[$THEME_NAME$]"
3224            },
3225            new String[] {
3226                String.valueOf(layoutSet.getGroupId()), themeId, themeName
3227            }
3228        );
3229
3230        FileUtil.deltree(themeLoader.getFileStorage() + "/" + themeId);
3231
3232        Iterator itr = entries.entrySet().iterator();
3233
3234        while (itr.hasNext()) {
3235            Map.Entry entry = (Map.Entry)itr.next();
3236
3237            String key = (String)entry.getKey();
3238            byte[] value = (byte[])entry.getValue();
3239
3240            if (key.equals("liferay-look-and-feel.xml")) {
3241                value = lookAndFeelXML.getBytes();
3242            }
3243
3244            FileUtil.write(
3245                themeLoader.getFileStorage() + "/" + themeId + "/" + key,
3246                value);
3247        }
3248
3249        themeLoader.loadThemes();
3250
3251        CommLink commLink = CommLink.getInstance();
3252
3253        MethodWrapper methodWrapper = new MethodWrapper(
3254            ThemeLoaderFactory.class.getName(), "loadThemes");
3255
3256        commLink.send(methodWrapper);
3257
3258        themeId +=
3259            PortletImpl.WAR_SEPARATOR + themeLoader.getServletContextName();
3260
3261        return PortalUtil.getJsSafePortletId(themeId);
3262    }
3263
3264    protected void importUserPermissions(
3265            LayoutCache layoutCache, long companyId, long groupId,
3266            String resourceName, String resourcePrimKey, Element parentEl,
3267            boolean portletActions)
3268        throws PortalException, SystemException {
3269
3270        Element userPermissionsEl = parentEl.element("user-permissions");
3271
3272        if (userPermissionsEl == null) {
3273            return;
3274        }
3275
3276        List userActionsEls = userPermissionsEl.elements("user-actions");
3277
3278        for (int i = 0; i < userActionsEls.size(); i++) {
3279            Element userActionsEl = (Element)userActionsEls.get(i);
3280
3281            String emailAddress = userActionsEl.attributeValue("email-address");
3282
3283            User user = layoutCache.getUser(companyId, groupId, emailAddress);
3284
3285            if (user == null) {
3286                if (_log.isWarnEnabled()) {
3287                    _log.warn(
3288                        "Ignoring permissions for user with email address " +
3289                            emailAddress);
3290                }
3291            }
3292            else {
3293                List actions = getActions(userActionsEl);
3294
3295                Resource resource = layoutCache.getResource(
3296                    companyId, groupId, resourceName,
3297                    ResourceImpl.SCOPE_INDIVIDUAL, resourcePrimKey,
3298                    portletActions);
3299
3300                permissionLocalService.setUserPermissions(
3301                    user.getUserId(), (String[])actions.toArray(new String[0]),
3302                    resource.getResourceId());
3303            }
3304        }
3305    }
3306
3307    protected void importUserRoles(
3308            LayoutCache layoutCache, long companyId, long groupId,
3309            String resourceName, Element parentEl)
3310        throws PortalException, SystemException {
3311
3312        Element userRolesEl = parentEl.element("user-roles");
3313
3314        if (userRolesEl == null) {
3315            return;
3316        }
3317
3318        LinkedHashMap params = new LinkedHashMap();
3319
3320        params.put("usersGroups", new Long(groupId));
3321
3322        List userEls = userRolesEl.elements("user");
3323
3324        for (int i = 0; i < userEls.size(); i++) {
3325            Element userEl = (Element)userEls.get(i);
3326
3327            String emailAddress = userEl.attributeValue("email-address");
3328
3329            User user = layoutCache.getUser(companyId, groupId, emailAddress);
3330
3331            if (user == null) {
3332                if (_log.isWarnEnabled()) {
3333                    _log.warn(
3334                        "Ignoring roles for user with email address " +
3335                            emailAddress);
3336                }
3337            }
3338            else {
3339                importRolePermissions(
3340                    layoutCache, companyId, resourceName,
3341                    ResourceImpl.SCOPE_GROUP, String.valueOf(groupId), userEl,
3342                    false);
3343            }
3344        }
3345    }
3346
3347    protected boolean isDescendant(Layout layout, long layoutId)
3348        throws PortalException, SystemException {
3349
3350        if (layout.getLayoutId() == layoutId) {
3351            return true;
3352        }
3353        else {
3354            Iterator itr = layout.getChildren().iterator();
3355
3356            while (itr.hasNext()) {
3357                Layout childLayout = (Layout)itr.next();
3358
3359                if (isDescendant(childLayout, layoutId)) {
3360                    return true;
3361                }
3362            }
3363
3364            return false;
3365        }
3366    }
3367
3368    protected void readComments(PortletDataContext context, Element root)
3369        throws PortalException, SystemException {
3370
3371        try {
3372            XStream xStream = new XStream();
3373
3374            Iterator itr = root.elements("comments").iterator();
3375
3376            while (itr.hasNext()) {
3377                Element el = (Element)itr.next();
3378
3379                String className = GetterUtil.getString(
3380                    el.attributeValue("class-name"));
3381                long classPK = GetterUtil.getLong(
3382                    el.attributeValue("class-pk"));
3383
3384                Element messagesListEl = el.element("list");
3385
3386                Document tempDoc = DocumentHelper.createDocument();
3387
3388                tempDoc.content().add(messagesListEl.createCopy());
3389
3390                List messages = (List)xStream.fromXML(
3391                    XMLFormatter.toString(tempDoc));
3392
3393                context.addComments(className, new Long(classPK), messages);
3394            }
3395        }
3396        catch (Exception e) {
3397            throw new SystemException(e);
3398        }
3399    }
3400
3401    protected void readRatings(PortletDataContext context, Element root)
3402        throws PortalException, SystemException {
3403
3404        try {
3405            XStream xStream = new XStream();
3406
3407            Iterator itr = root.elements("ratings").iterator();
3408
3409            while (itr.hasNext()) {
3410                Element el = (Element)itr.next();
3411
3412                String className = GetterUtil.getString(
3413                    el.attributeValue("class-name"));
3414                long classPK = GetterUtil.getLong(
3415                    el.attributeValue("class-pk"));
3416
3417                Element entriesListEl = el.element("list");
3418
3419                Document tempDoc = DocumentHelper.createDocument();
3420
3421                tempDoc.content().add(entriesListEl.createCopy());
3422
3423                List entries = (List)xStream.fromXML(
3424                    XMLFormatter.toString(tempDoc));
3425
3426                context.addRatingsEntries(
3427                    className, new Long(classPK), entries);
3428            }
3429        }
3430        catch (Exception e) {
3431            throw new SystemException(e);
3432        }
3433    }
3434
3435    protected void readTags(PortletDataContext context, Element root)
3436        throws PortalException, SystemException {
3437
3438        Iterator itr = root.elements("tags").iterator();
3439
3440        while (itr.hasNext()) {
3441            Element el = (Element)itr.next();
3442
3443            String className = GetterUtil.getString(
3444                el.attributeValue("class-name"));
3445            long classPK = GetterUtil.getLong(el.attributeValue("class-pk"));
3446            String entries = GetterUtil.getString(el.attributeValue("entries"));
3447
3448            context.addTagsEntries(
3449                className, new Long(classPK), StringUtil.split(entries, ","));
3450        }
3451    }
3452
3453    protected void setLocalizedAttributes(
3454        Layout layout, Map localeNamesMap, Map localeTitlesMap) {
3455
3456        Locale[] locales = LanguageUtil.getAvailableLocales();
3457
3458        for (int i = 0; i < locales.length; i++) {
3459            String name = (String)localeNamesMap.get(locales[i]);
3460            String title = (String)localeTitlesMap.get(locales[i]);
3461
3462            layout.setName(name, locales[i]);
3463            layout.setTitle(title, locales[i]);
3464        }
3465    }
3466
3467    protected void validate(
3468            long groupId, boolean privateLayout, long layoutId,
3469            long parentLayoutId, String type, boolean hidden,
3470            String friendlyURL)
3471        throws PortalException, SystemException {
3472
3473        boolean firstLayout = false;
3474
3475        if (parentLayoutId == LayoutImpl.DEFAULT_PARENT_LAYOUT_ID) {
3476            List layouts = layoutPersistence.findByG_P_P(
3477                groupId, privateLayout, parentLayoutId, 0, 1);
3478
3479            if (layouts.size() == 0) {
3480                firstLayout = true;
3481            }
3482            else {
3483                long firstLayoutId = ((Layout)layouts.get(0)).getLayoutId();
3484
3485                if (firstLayoutId == layoutId) {
3486                    firstLayout = true;
3487                }
3488            }
3489        }
3490
3491        if (firstLayout) {
3492            validateFirstLayout(type, hidden);
3493        }
3494
3495        if (!PortalUtil.isLayoutParentable(type)) {
3496            if (layoutPersistence.countByG_P_P(
3497                    groupId, privateLayout, layoutId) > 0) {
3498
3499                throw new LayoutTypeException(
3500                    LayoutTypeException.NOT_PARENTABLE);
3501            }
3502        }
3503
3504        if (Validator.isNotNull(friendlyURL)) {
3505            int exceptionType = LayoutImpl.validateFriendlyURL(friendlyURL);
3506
3507            if (exceptionType != -1) {
3508                throw new LayoutFriendlyURLException(exceptionType);
3509            }
3510
3511            try {
3512                Layout layout = layoutPersistence.findByG_P_F(
3513                    groupId, privateLayout, friendlyURL);
3514
3515                if (layout.getLayoutId() != layoutId) {
3516                    throw new LayoutFriendlyURLException(
3517                        LayoutFriendlyURLException.DUPLICATE);
3518                }
3519            }
3520            catch (NoSuchLayoutException nsle) {
3521            }
3522
3523            LayoutImpl.validateFriendlyURLKeyword(friendlyURL);
3524
3525            List friendlyURLMappers =
3526                portletLocalService.getFriendlyURLMappers();
3527
3528            Iterator itr = friendlyURLMappers.iterator();
3529
3530            while (itr.hasNext()) {
3531                FriendlyURLMapper friendlyURLMapper =
3532                    (FriendlyURLMapper)itr.next();
3533
3534                if (friendlyURL.indexOf(friendlyURLMapper.getMapping()) != -1) {
3535                    LayoutFriendlyURLException lfurle =
3536                        new LayoutFriendlyURLException(
3537                            LayoutFriendlyURLException.KEYWORD_CONFLICT);
3538
3539                    lfurle.setKeywordConflict(friendlyURLMapper.getMapping());
3540
3541                    throw lfurle;
3542                }
3543            }
3544
3545        }
3546    }
3547
3548    protected void validateFirstLayout(String type, boolean hidden)
3549        throws PortalException {
3550
3551        if (!type.equals(LayoutImpl.TYPE_PORTLET)) {
3552            throw new LayoutTypeException(LayoutTypeException.FIRST_LAYOUT);
3553        }
3554
3555        if (hidden) {
3556            throw new LayoutHiddenException();
3557        }
3558    }
3559
3560    protected void validateParentLayoutId(
3561            long groupId, boolean privateLayout, long layoutId,
3562            long parentLayoutId)
3563        throws PortalException, SystemException {
3564
3565        Layout layout = layoutPersistence.findByG_P_L(
3566            groupId, privateLayout, layoutId);
3567
3568        if (parentLayoutId != layout.getParentLayoutId()) {
3569
3570            // Layouts can always be moved to the root level
3571
3572            if (parentLayoutId == LayoutImpl.DEFAULT_PARENT_LAYOUT_ID) {
3573                return;
3574            }
3575
3576            // Layout cannot become a child of a layout that is not parentable
3577
3578            Layout parentLayout = layoutPersistence.findByG_P_L(
3579                groupId, privateLayout, parentLayoutId);
3580
3581            if (!PortalUtil.isLayoutParentable(parentLayout)) {
3582                throw new LayoutParentLayoutIdException(
3583                    LayoutParentLayoutIdException.NOT_PARENTABLE);
3584            }
3585
3586            // Layout cannot become descendant of itself
3587
3588            if (isDescendant(layout, parentLayoutId)) {
3589                throw new LayoutParentLayoutIdException(
3590                    LayoutParentLayoutIdException.SELF_DESCENDANT);
3591            }
3592
3593            // If layout is moved, the new first layout must be valid
3594
3595            if (layout.getParentLayoutId() ==
3596                    LayoutImpl.DEFAULT_PARENT_LAYOUT_ID) {
3597
3598                List layouts = layoutPersistence.findByG_P_P(
3599                    groupId, privateLayout,
3600                    LayoutImpl.DEFAULT_PARENT_LAYOUT_ID, 0, 2);
3601
3602                // You can only reach this point if there are more than two
3603                // layouts at the root level because of the descendant check
3604
3605                long firstLayoutId = ((Layout)layouts.get(0)).getLayoutId();
3606
3607                if (firstLayoutId == layoutId) {
3608                    Layout secondLayout = (Layout)layouts.get(1);
3609
3610                    try {
3611                        validateFirstLayout(
3612                            secondLayout.getType(), secondLayout.getHidden());
3613                    }
3614                    catch (LayoutHiddenException lhe) {
3615                        throw new LayoutParentLayoutIdException(
3616                            LayoutParentLayoutIdException.FIRST_LAYOUT_HIDDEN);
3617                    }
3618                    catch (LayoutTypeException lte) {
3619                        throw new LayoutParentLayoutIdException(
3620                            LayoutParentLayoutIdException.FIRST_LAYOUT_TYPE);
3621                    }
3622                }
3623            }
3624        }
3625    }
3626
3627    private static Log _log = LogFactory.getLog(LayoutLocalServiceImpl.class);
3628
3629}