1   /**
2    * Copyright (c) 2000-2009 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.LayoutParentLayoutIdException;
28  import com.liferay.portal.LayoutTypeException;
29  import com.liferay.portal.NoSuchLayoutException;
30  import com.liferay.portal.PortalException;
31  import com.liferay.portal.RequiredLayoutException;
32  import com.liferay.portal.SystemException;
33  import com.liferay.portal.kernel.io.FileCacheOutputStream;
34  import com.liferay.portal.kernel.language.LanguageUtil;
35  import com.liferay.portal.kernel.log.Log;
36  import com.liferay.portal.kernel.log.LogFactoryUtil;
37  import com.liferay.portal.kernel.util.GetterUtil;
38  import com.liferay.portal.kernel.util.ListUtil;
39  import com.liferay.portal.kernel.util.LocaleUtil;
40  import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
41  import com.liferay.portal.kernel.util.StringPool;
42  import com.liferay.portal.kernel.util.Validator;
43  import com.liferay.portal.lar.LayoutExporter;
44  import com.liferay.portal.lar.LayoutImporter;
45  import com.liferay.portal.lar.PortletExporter;
46  import com.liferay.portal.lar.PortletImporter;
47  import com.liferay.portal.model.Group;
48  import com.liferay.portal.model.Layout;
49  import com.liferay.portal.model.LayoutConstants;
50  import com.liferay.portal.model.LayoutReference;
51  import com.liferay.portal.model.LayoutTypePortlet;
52  import com.liferay.portal.model.PortletConstants;
53  import com.liferay.portal.model.Resource;
54  import com.liferay.portal.model.ResourceConstants;
55  import com.liferay.portal.model.User;
56  import com.liferay.portal.model.impl.LayoutImpl;
57  import com.liferay.portal.service.base.LayoutLocalServiceBaseImpl;
58  import com.liferay.portal.service.persistence.BatchSessionUtil;
59  import com.liferay.portal.util.FriendlyURLNormalizer;
60  import com.liferay.portal.util.PortalUtil;
61  import com.liferay.portal.util.PortletKeys;
62  import com.liferay.portal.util.PropsValues;
63  import com.liferay.portal.util.comparator.LayoutPriorityComparator;
64  import com.liferay.portlet.documentlibrary.DuplicateFolderNameException;
65  import com.liferay.portlet.documentlibrary.NoSuchFolderException;
66  import com.liferay.portlet.documentlibrary.model.DLFolder;
67  import com.liferay.portlet.documentlibrary.model.impl.DLFolderImpl;
68  
69  import java.io.ByteArrayInputStream;
70  import java.io.File;
71  import java.io.FileInputStream;
72  import java.io.FileNotFoundException;
73  import java.io.IOException;
74  import java.io.InputStream;
75  
76  import java.util.ArrayList;
77  import java.util.Date;
78  import java.util.HashMap;
79  import java.util.HashSet;
80  import java.util.LinkedHashSet;
81  import java.util.List;
82  import java.util.Locale;
83  import java.util.Map;
84  import java.util.Set;
85  
86  /**
87   * <a href="LayoutLocalServiceImpl.java.html"><b><i>View Source</i></b></a>
88   *
89   * @author Brian Wing Shun Chan
90   * @author Joel Kozikowski
91   * @author Charles May
92   * @author Raymond Augé
93   * @author Jorge Ferrer
94   * @author Bruno Farache
95   *
96   */
97  public class LayoutLocalServiceImpl extends LayoutLocalServiceBaseImpl {
98  
99      public Layout addLayout(
100             long userId, long groupId, boolean privateLayout,
101             long parentLayoutId, String name, String title, String description,
102             String type, boolean hidden, String friendlyURL)
103         throws PortalException, SystemException {
104 
105         Map<Locale, String> localeNamesMap = new HashMap<Locale, String>();
106 
107         Locale defaultLocale = LocaleUtil.getDefault();
108 
109         localeNamesMap.put(defaultLocale, name);
110 
111         return addLayout(
112             userId, groupId, privateLayout, parentLayoutId, localeNamesMap,
113             new HashMap<Locale, String>(), description, type, hidden,
114             friendlyURL);
115     }
116 
117     public Layout addLayout(
118             long userId, long groupId, boolean privateLayout,
119             long parentLayoutId, Map<Locale, String> localeNamesMap,
120             Map<Locale, String> localeTitlesMap, String description,
121             String type, boolean hidden, String friendlyURL)
122         throws PortalException, SystemException {
123 
124         return addLayout(
125             userId, groupId, privateLayout, parentLayoutId, localeNamesMap,
126             localeTitlesMap, description, type, hidden, friendlyURL,
127             DLFolderImpl.DEFAULT_PARENT_FOLDER_ID);
128     }
129 
130     public Layout addLayout(
131             long userId, long groupId, boolean privateLayout,
132             long parentLayoutId, String name, String title, String description,
133             String type, boolean hidden, String friendlyURL, long dlFolderId)
134         throws PortalException, SystemException {
135 
136         Map<Locale, String> localeNamesMap = new HashMap<Locale, String>();
137 
138         Locale defaultLocale = LocaleUtil.getDefault();
139 
140         localeNamesMap.put(defaultLocale, name);
141 
142         return addLayout(
143             userId, groupId, privateLayout, parentLayoutId, localeNamesMap,
144             null, description, type, hidden, friendlyURL, dlFolderId);
145     }
146 
147     public Layout addLayout(
148             long userId, long groupId, boolean privateLayout,
149             long parentLayoutId, Map<Locale, String> localeNamesMap,
150             Map<Locale, String> localeTitlesMap, String description,
151             String type, boolean hidden, String friendlyURL, long dlFolderId)
152         throws PortalException, SystemException {
153 
154         // Layout
155 
156         User user = userPersistence.findByPrimaryKey(userId);
157         long layoutId = getNextLayoutId(groupId, privateLayout);
158         parentLayoutId = getParentLayoutId(
159             groupId, privateLayout, parentLayoutId);
160         String friendlyName = localeNamesMap.get(LocaleUtil.getDefault());
161         friendlyURL = getFriendlyURL(
162             groupId, privateLayout, layoutId, friendlyName, friendlyURL);
163         int priority = getNextPriority(groupId, privateLayout, parentLayoutId);
164 
165         validate(
166             groupId, privateLayout, layoutId, parentLayoutId, type, hidden,
167             friendlyURL);
168 
169         long plid = counterLocalService.increment();
170 
171         Layout layout = layoutPersistence.create(plid);
172 
173         layout.setGroupId(groupId);
174         layout.setCompanyId(user.getCompanyId());
175         layout.setPrivateLayout(privateLayout);
176         layout.setLayoutId(layoutId);
177         layout.setParentLayoutId(parentLayoutId);
178         layout.setDescription(description);
179         layout.setType(type);
180         layout.setHidden(hidden);
181         layout.setFriendlyURL(friendlyURL);
182         layout.setPriority(priority);
183         layout.setDlFolderId(dlFolderId);
184 
185         setLocalizedAttributes(layout, localeNamesMap, localeTitlesMap);
186 
187         if (type.equals(LayoutConstants.TYPE_PORTLET)) {
188             LayoutTypePortlet layoutTypePortlet =
189                 (LayoutTypePortlet)layout.getLayoutType();
190 
191             layoutTypePortlet.setLayoutTemplateId(
192                 0, PropsValues.LAYOUT_DEFAULT_TEMPLATE_ID, false);
193         }
194 
195         layoutPersistence.update(layout, false);
196 
197         // Resources
198 
199         resourceLocalService.addResources(
200             user.getCompanyId(), groupId, user.getUserId(),
201             Layout.class.getName(), layout.getPlid(), false, true, true);
202 
203         // Layout set
204 
205         layoutSetLocalService.updatePageCount(groupId, privateLayout);
206 
207         return layout;
208     }
209 
210     public void deleteLayout(long plid)
211         throws PortalException, SystemException {
212 
213         Layout layout = layoutPersistence.findByPrimaryKey(plid);
214 
215         deleteLayout(layout, true);
216     }
217 
218     public void deleteLayout(long groupId, boolean privateLayout, long layoutId)
219         throws PortalException, SystemException {
220 
221         Layout layout = layoutPersistence.findByG_P_L(
222             groupId, privateLayout, layoutId);
223 
224         deleteLayout(layout, true);
225     }
226 
227     public void deleteLayout(Layout layout, boolean updateLayoutSet)
228         throws PortalException, SystemException {
229 
230         // Child layouts
231 
232         List<Layout> childLayouts = layoutPersistence.findByG_P_P(
233             layout.getGroupId(), layout.isPrivateLayout(),
234             layout.getLayoutId());
235 
236         for (Layout childLayout : childLayouts) {
237             deleteLayout(childLayout, updateLayoutSet);
238         }
239 
240         // Portlet preferences
241 
242         portletPreferencesLocalService.deletePortletPreferences(
243             PortletKeys.PREFS_OWNER_ID_DEFAULT,
244             PortletKeys.PREFS_OWNER_TYPE_LAYOUT, layout.getPlid());
245 
246         // Tasks
247 
248         tasksProposalLocalService.deleteProposal(
249             Layout.class.getName(), String.valueOf(layout.getPlid()));
250 
251         // Ratings
252 
253         ratingsStatsLocalService.deleteStats(
254             Layout.class.getName(), layout.getPlid());
255 
256         // Message boards
257 
258         mbMessageLocalService.deleteDiscussionMessages(
259             Layout.class.getName(), layout.getPlid());
260 
261         // Journal content searches
262 
263         journalContentSearchLocalService.deleteLayoutContentSearches(
264             layout.getGroupId(), layout.isPrivateLayout(),
265             layout.getLayoutId());
266 
267         // Icon
268 
269         imageLocalService.deleteImage(layout.getIconImageId());
270 
271         // Scope group
272 
273         Group scopeGroup = layout.getScopeGroup();
274 
275         if (scopeGroup != null) {
276             groupLocalService.deleteGroup(scopeGroup.getGroupId());
277         }
278 
279         // Resources
280 
281         String primKey =
282             layout.getPlid() + PortletConstants.LAYOUT_SEPARATOR + "%";
283 
284         List<Resource> resources = resourceFinder.findByC_P(
285             layout.getCompanyId(), primKey);
286 
287         for (Resource resource : resources) {
288             resourceLocalService.deleteResource(resource);
289         }
290 
291         resourceLocalService.deleteResource(
292             layout.getCompanyId(), Layout.class.getName(),
293             ResourceConstants.SCOPE_INDIVIDUAL, layout.getPlid());
294 
295         // Layout
296 
297         layoutPersistence.remove(layout);
298 
299         // Layout set
300 
301         if (updateLayoutSet) {
302             layoutSetLocalService.updatePageCount(
303                 layout.getGroupId(), layout.isPrivateLayout());
304         }
305     }
306 
307     public void deleteLayouts(long groupId, boolean privateLayout)
308         throws PortalException, SystemException {
309 
310         // Layouts
311 
312         List<Layout> layouts = layoutPersistence.findByG_P_P(
313             groupId, privateLayout, LayoutConstants.DEFAULT_PARENT_LAYOUT_ID);
314 
315         for (Layout layout : layouts) {
316             try {
317                 deleteLayout(layout, false);
318             }
319             catch (NoSuchLayoutException nsle) {
320             }
321         }
322 
323         // Layout set
324 
325         layoutSetLocalService.updatePageCount(groupId, privateLayout);
326     }
327 
328     public byte[] exportLayouts(
329             long groupId, boolean privateLayout,
330             Map<String, String[]> parameterMap, Date startDate, Date endDate)
331         throws PortalException, SystemException {
332 
333         return exportLayouts(
334             groupId, privateLayout, null, parameterMap, startDate, endDate);
335     }
336 
337     public byte[] exportLayouts(
338             long groupId, boolean privateLayout, long[] layoutIds,
339             Map<String, String[]> parameterMap, Date startDate, Date endDate)
340         throws PortalException, SystemException {
341 
342         FileCacheOutputStream fcos = exportLayoutsAsStream(
343             groupId, privateLayout, layoutIds, parameterMap, startDate,
344             endDate);
345 
346         try {
347             return fcos.getBytes();
348         }
349         catch (IOException ioe) {
350             throw new SystemException(ioe);
351         }
352     }
353 
354     public FileCacheOutputStream exportLayoutsAsStream(
355             long groupId, boolean privateLayout, long[] layoutIds,
356             Map<String, String[]> parameterMap, Date startDate, Date endDate)
357         throws PortalException, SystemException {
358 
359         LayoutExporter layoutExporter = new LayoutExporter();
360 
361         return layoutExporter.exportLayoutsAsStream(
362             groupId, privateLayout, layoutIds, parameterMap, startDate,
363             endDate);
364     }
365 
366     public byte[] exportPortletInfo(
367             long plid, long groupId, String portletId,
368             Map<String, String[]> parameterMap, Date startDate, Date endDate)
369         throws PortalException, SystemException {
370 
371         FileCacheOutputStream fcos = exportPortletInfoAsStream(
372             plid, groupId, portletId, parameterMap, startDate, endDate);
373 
374         try {
375             return fcos.getBytes();
376         }
377         catch (IOException ioe) {
378             throw new SystemException(ioe);
379         }
380     }
381 
382     public FileCacheOutputStream exportPortletInfoAsStream(
383             long plid, long groupId, String portletId,
384             Map<String, String[]> parameterMap, Date startDate, Date endDate)
385         throws PortalException, SystemException {
386 
387         PortletExporter portletExporter = new PortletExporter();
388 
389         return portletExporter.exportPortletInfoAsStream(
390             plid, groupId, portletId, parameterMap, startDate, endDate);
391     }
392 
393     public long getDefaultPlid(long groupId) throws SystemException {
394         if (groupId > 0) {
395             List<Layout> layouts = layoutPersistence.findByGroupId(
396                 groupId, 0, 1);
397 
398             if (layouts.size() > 0) {
399                 Layout layout = layouts.get(0);
400 
401                 return layout.getPlid();
402             }
403         }
404 
405         return LayoutConstants.DEFAULT_PLID;
406     }
407 
408     public long getDefaultPlid(long groupId, boolean privateLayout)
409         throws SystemException {
410 
411         if (groupId > 0) {
412             List<Layout> layouts = layoutPersistence.findByG_P(
413                 groupId, privateLayout, 0, 1);
414 
415             if (layouts.size() > 0) {
416                 Layout layout = layouts.get(0);
417 
418                 return layout.getPlid();
419             }
420         }
421 
422         return LayoutConstants.DEFAULT_PLID;
423     }
424 
425     public long getDefaultPlid(
426             long groupId, boolean privateLayout, String portletId)
427         throws SystemException {
428 
429         if (groupId > 0) {
430             List<Layout> layouts = layoutPersistence.findByG_P(
431                 groupId, privateLayout);
432 
433             for (Layout layout : layouts) {
434                 if (layout.getType().equals(LayoutConstants.TYPE_PORTLET)) {
435                     LayoutTypePortlet layoutTypePortlet =
436                         (LayoutTypePortlet)layout.getLayoutType();
437 
438                     if (layoutTypePortlet.hasPortletId(portletId)) {
439                         return layout.getPlid();
440                     }
441                 }
442             }
443         }
444 
445         return LayoutConstants.DEFAULT_PLID;
446     }
447 
448     public Layout getDLFolderLayout(long dlFolderId)
449         throws PortalException, SystemException {
450 
451         return layoutPersistence.findByDLFolderId(dlFolderId);
452     }
453 
454     public Layout getFriendlyURLLayout(
455             long groupId, boolean privateLayout, String friendlyURL)
456         throws PortalException, SystemException {
457 
458         if (Validator.isNull(friendlyURL)) {
459             throw new NoSuchLayoutException();
460         }
461 
462         friendlyURL = getFriendlyURL(friendlyURL);
463 
464         Layout layout = layoutPersistence.fetchByG_P_F(
465             groupId, privateLayout, friendlyURL);
466 
467         if ((layout == null) &&
468             (friendlyURL.startsWith(StringPool.SLASH))) {
469 
470             long layoutId = GetterUtil.getLong(friendlyURL.substring(1));
471 
472             layout = layoutPersistence.fetchByG_P_L(
473                 groupId, privateLayout, layoutId);
474         }
475 
476         if (layout == null) {
477             throw new NoSuchLayoutException();
478         }
479 
480         return layout;
481     }
482 
483     public Layout getLayout(long plid)
484         throws PortalException, SystemException {
485 
486         return layoutPersistence.findByPrimaryKey(plid);
487     }
488 
489     public Layout getLayout(long groupId, boolean privateLayout, long layoutId)
490         throws PortalException, SystemException {
491 
492         return layoutPersistence.findByG_P_L(groupId, privateLayout, layoutId);
493     }
494 
495     public Layout getLayoutByIconImageId(long iconImageId)
496         throws PortalException, SystemException {
497 
498         return layoutPersistence.findByIconImageId(iconImageId);
499     }
500 
501     public List<Layout> getLayouts(long groupId, boolean privateLayout)
502         throws SystemException {
503 
504         return layoutPersistence.findByG_P(groupId, privateLayout);
505     }
506 
507     public List<Layout> getLayouts(
508             long groupId, boolean privateLayout, long parentLayoutId)
509         throws SystemException {
510 
511         return layoutPersistence.findByG_P_P(
512             groupId, privateLayout, parentLayoutId);
513     }
514 
515     public List<Layout> getLayouts(
516             long groupId, boolean privateLayout, String type)
517         throws SystemException {
518 
519         return layoutPersistence.findByG_P_T(groupId, privateLayout, type);
520     }
521 
522     public List<Layout> getLayouts(
523             long groupId, boolean privateLayout, long parentLayoutId, int start,
524             int end)
525         throws SystemException {
526 
527         return layoutPersistence.findByG_P_P(
528             groupId, privateLayout, parentLayoutId, start, end);
529     }
530 
531     public List<Layout> getLayouts(
532             long groupId, boolean privateLayout, long[] layoutIds)
533         throws PortalException, SystemException {
534 
535         List<Layout> layouts = new ArrayList<Layout>();
536 
537         for (long layoutId : layoutIds) {
538             Layout layout = getLayout(groupId, privateLayout, layoutId);
539 
540             layouts.add(layout);
541         }
542 
543         return layouts;
544     }
545 
546     public LayoutReference[] getLayouts(
547             long companyId, String portletId, String preferencesKey,
548             String preferencesValue)
549         throws SystemException {
550 
551         List<LayoutReference> layoutReferences = layoutFinder.findByC_P_P(
552             companyId, portletId, preferencesKey, preferencesValue);
553 
554         return layoutReferences.toArray(
555             new LayoutReference[layoutReferences.size()]);
556     }
557 
558     public long getNextLayoutId(long groupId, boolean privateLayout)
559         throws SystemException {
560 
561         long layoutId = 0;
562 
563         List<Layout> layouts = layoutPersistence.findByG_P(
564             groupId, privateLayout);
565 
566         for (Layout curLayout : layouts) {
567             long curLayoutId = curLayout.getLayoutId();
568 
569             if (curLayoutId > layoutId) {
570                 layoutId = curLayoutId;
571             }
572         }
573 
574         return ++layoutId;
575     }
576 
577     public List<Layout> getNullFriendlyURLLayouts() throws SystemException {
578         return layoutFinder.findByNullFriendlyURL();
579     }
580 
581     public void importLayouts(
582             long userId, long groupId, boolean privateLayout,
583             Map<String, String[]> parameterMap, File file)
584         throws PortalException, SystemException {
585 
586         try {
587             importLayouts(
588                 userId, groupId, privateLayout, parameterMap,
589                 new FileInputStream(file));
590         }
591         catch (FileNotFoundException fnfe) {
592             throw new SystemException(fnfe);
593         }
594     }
595 
596     public void importLayouts(
597             long userId, long groupId, boolean privateLayout,
598             Map<String, String[]> parameterMap, byte[] bytes)
599         throws PortalException, SystemException {
600 
601         importLayouts(
602             userId, groupId, privateLayout, parameterMap,
603             new ByteArrayInputStream(bytes));
604     }
605 
606     public void importLayouts(
607             long userId, long groupId, boolean privateLayout,
608             Map<String, String[]> parameterMap, InputStream is)
609         throws PortalException, SystemException {
610 
611         BatchSessionUtil.setEnabled(true);
612 
613         try {
614             LayoutImporter layoutImporter = new LayoutImporter();
615 
616             layoutImporter.importLayouts(
617                 userId, groupId, privateLayout, parameterMap, is);
618         }
619         finally {
620             BatchSessionUtil.setEnabled(false);
621         }
622     }
623 
624     public void importPortletInfo(
625             long userId, long plid, long groupId, String portletId,
626             Map<String, String[]> parameterMap, File file)
627         throws PortalException, SystemException {
628 
629         try {
630             importPortletInfo(
631                 userId, plid, groupId, portletId, parameterMap,
632                 new FileInputStream(file));
633         }
634         catch (FileNotFoundException fnfe) {
635             throw new SystemException(fnfe);
636         }
637     }
638 
639     public void importPortletInfo(
640             long userId, long plid, long groupId, String portletId,
641             Map<String, String[]> parameterMap, InputStream is)
642         throws PortalException, SystemException {
643 
644         BatchSessionUtil.setEnabled(true);
645 
646         try {
647             PortletImporter portletImporter = new PortletImporter();
648 
649             portletImporter.importPortletInfo(
650                 userId, plid, groupId, portletId, parameterMap, is);
651         }
652         finally {
653             BatchSessionUtil.setEnabled(false);
654         }
655     }
656 
657     public void setLayouts(
658             long groupId, boolean privateLayout, long parentLayoutId,
659             long[] layoutIds)
660         throws PortalException, SystemException {
661 
662         if (layoutIds == null) {
663             return;
664         }
665 
666         if (parentLayoutId == LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
667             if (layoutIds.length < 1) {
668                 throw new RequiredLayoutException(
669                     RequiredLayoutException.AT_LEAST_ONE);
670             }
671 
672             Layout layout = layoutPersistence.findByG_P_L(
673                 groupId, privateLayout, layoutIds[0]);
674 
675             if (!PortalUtil.isLayoutFirstPageable(layout.getType())) {
676                 throw new RequiredLayoutException(
677                     RequiredLayoutException.FIRST_LAYOUT_TYPE);
678             }
679 
680             if (layout.isHidden()) {
681                 throw new RequiredLayoutException(
682                     RequiredLayoutException.FIRST_LAYOUT_HIDDEN);
683             }
684         }
685 
686         Set<Long> layoutIdsSet = new LinkedHashSet<Long>();
687 
688         for (int i = 0; i < layoutIds.length; i++) {
689             layoutIdsSet.add(layoutIds[i]);
690         }
691 
692         Set<Long> newLayoutIdsSet = new HashSet<Long>();
693 
694         List<Layout> layouts = layoutPersistence.findByG_P_P(
695             groupId, privateLayout, parentLayoutId);
696 
697         for (Layout layout : layouts) {
698             if (!layoutIdsSet.contains(layout.getLayoutId())) {
699                 deleteLayout(layout, true);
700             }
701             else {
702                 newLayoutIdsSet.add(layout.getLayoutId());
703             }
704         }
705 
706         int priority = 0;
707 
708         for (long layoutId : layoutIdsSet) {
709             Layout layout = layoutPersistence.findByG_P_L(
710                 groupId, privateLayout, layoutId);
711 
712             layout.setPriority(priority++);
713 
714             layoutPersistence.update(layout, false);
715         }
716 
717         layoutSetLocalService.updatePageCount(groupId, privateLayout);
718     }
719 
720     public Layout updateFriendlyURL(long plid, String friendlyURL)
721         throws PortalException, SystemException {
722 
723         Layout layout = layoutPersistence.findByPrimaryKey(plid);
724 
725         friendlyURL = getFriendlyURL(
726             layout.getGroupId(), layout.getPrivateLayout(),
727             layout.getLayoutId(), StringPool.BLANK, friendlyURL);
728 
729         validateFriendlyURL(
730             layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(),
731             friendlyURL);
732 
733         layout.setFriendlyURL(friendlyURL);
734 
735         layoutPersistence.update(layout, false);
736 
737         return layout;
738     }
739 
740     public Layout updateLayout(
741             long groupId, boolean privateLayout, long layoutId,
742             long parentLayoutId, Map<Locale, String> localeNamesMap,
743             Map<Locale, String> localeTitlesMap, String description,
744             String type, boolean hidden, String friendlyURL)
745         throws PortalException, SystemException {
746 
747         return updateLayout(
748             groupId, privateLayout, layoutId, parentLayoutId, localeNamesMap,
749             localeTitlesMap, description, type, hidden, friendlyURL, null,
750             null);
751     }
752 
753     public Layout updateLayout(
754             long groupId, boolean privateLayout, long layoutId,
755             long parentLayoutId, Map<Locale, String> localeNamesMap,
756             Map<Locale, String> localeTitlesMap, String description,
757             String type, boolean hidden, String friendlyURL, Boolean iconImage,
758             byte[] iconBytes)
759         throws PortalException, SystemException {
760 
761         // Layout
762 
763         parentLayoutId = getParentLayoutId(
764             groupId, privateLayout, parentLayoutId);
765         friendlyURL = getFriendlyURL(
766             groupId, privateLayout, layoutId, StringPool.BLANK, friendlyURL);
767 
768         validate(
769             groupId, privateLayout, layoutId, parentLayoutId, type, hidden,
770             friendlyURL);
771 
772         validateParentLayoutId(
773             groupId, privateLayout, layoutId, parentLayoutId);
774 
775         Layout layout = layoutPersistence.findByG_P_L(
776             groupId, privateLayout, layoutId);
777 
778         if (parentLayoutId != layout.getParentLayoutId()) {
779             layout.setPriority(
780                 getNextPriority(groupId, privateLayout, parentLayoutId));
781         }
782 
783         layout.setParentLayoutId(parentLayoutId);
784         layout.setDescription(description);
785         layout.setType(type);
786         layout.setHidden(hidden);
787         layout.setFriendlyURL(friendlyURL);
788 
789         setLocalizedAttributes(layout, localeNamesMap, localeTitlesMap);
790 
791         if (iconImage != null) {
792             layout.setIconImage(iconImage.booleanValue());
793 
794             if (iconImage.booleanValue()) {
795                 long iconImageId = layout.getIconImageId();
796 
797                 if (iconImageId <= 0) {
798                     iconImageId = counterLocalService.increment();
799 
800                     layout.setIconImageId(iconImageId);
801                 }
802             }
803         }
804 
805         layoutPersistence.update(layout, false);
806 
807         // Icon
808 
809         if (iconImage != null) {
810             if (!iconImage.booleanValue()) {
811                 imageLocalService.deleteImage(layout.getIconImageId());
812             }
813             else if ((iconBytes != null) && (iconBytes.length > 0)) {
814                 imageLocalService.updateImage(
815                     layout.getIconImageId(), iconBytes);
816             }
817         }
818 
819         try {
820             if (layout.getDlFolderId() > 0) {
821                 DLFolder folder = dlFolderLocalService.getFolder(
822                     layout.getDlFolderId());
823 
824                 String name = layout.getName(LocaleUtil.getDefault());
825 
826                 if (!name.equals(folder.getName())) {
827                     dlFolderLocalService.updateFolder(
828                         folder.getFolderId(), folder.getParentFolderId(), name,
829                         folder.getDescription());
830                 }
831             }
832         }
833         catch (DuplicateFolderNameException dfne) {
834             if (_log.isDebugEnabled()) {
835                 _log.debug(dfne);
836             }
837         }
838         catch (NoSuchFolderException nsfe) {
839         }
840 
841         return layout;
842     }
843 
844     public Layout updateLayout(
845             long groupId, boolean privateLayout, long layoutId,
846             String typeSettings)
847         throws PortalException, SystemException {
848 
849         Layout layout = layoutPersistence.findByG_P_L(
850             groupId, privateLayout, layoutId);
851 
852         layout.setTypeSettings(typeSettings);
853 
854         layoutPersistence.update(layout, false);
855 
856         return layout;
857     }
858 
859     public Layout updateLookAndFeel(
860             long groupId, boolean privateLayout, long layoutId, String themeId,
861             String colorSchemeId, String css, boolean wapTheme)
862         throws PortalException, SystemException {
863 
864         Layout layout = layoutPersistence.findByG_P_L(
865             groupId, privateLayout, layoutId);
866 
867         if (wapTheme) {
868             layout.setWapThemeId(themeId);
869             layout.setWapColorSchemeId(colorSchemeId);
870         }
871         else {
872             layout.setThemeId(themeId);
873             layout.setColorSchemeId(colorSchemeId);
874             layout.setCss(css);
875         }
876 
877         layoutPersistence.update(layout, false);
878 
879         return layout;
880     }
881 
882     public Layout updateName(long plid, String name, String languageId)
883         throws PortalException, SystemException {
884 
885         Layout layout = layoutPersistence.findByPrimaryKey(plid);
886 
887         return updateName(layout, name, languageId);
888     }
889 
890     public Layout updateName(
891             long groupId, boolean privateLayout, long layoutId, String name,
892             String languageId)
893         throws PortalException, SystemException {
894 
895         Layout layout = layoutPersistence.findByG_P_L(
896             groupId, privateLayout, layoutId);
897 
898         return updateName(layout, name, languageId);
899     }
900 
901     public Layout updateName(Layout layout, String name, String languageId)
902         throws PortalException, SystemException {
903 
904         layout.setName(name, LocaleUtil.fromLanguageId(languageId));
905 
906         layoutPersistence.update(layout, false);
907 
908         try {
909             if (layout.getDlFolderId() > 0) {
910                 DLFolder folder = dlFolderLocalService.getFolder(
911                     layout.getDlFolderId());
912 
913                 dlFolderLocalService.updateFolder(
914                     folder.getFolderId(), folder.getParentFolderId(),
915                     layout.getName(LocaleUtil.getDefault()),
916                     folder.getDescription());
917             }
918         }
919         catch (NoSuchFolderException nsfe) {
920         }
921 
922         return layout;
923     }
924 
925     public Layout updateParentLayoutId(long plid, long parentPlid)
926         throws PortalException, SystemException {
927 
928         Layout layout = layoutPersistence.findByPrimaryKey(plid);
929 
930         long parentLayoutId = LayoutConstants.DEFAULT_PARENT_LAYOUT_ID;
931 
932         if (parentPlid > 0) {
933             Layout parentLayout = layoutPersistence.fetchByPrimaryKey(
934                 parentPlid);
935 
936             if (parentLayout != null) {
937                 parentLayoutId = parentLayout.getLayoutId();
938             }
939         }
940 
941         parentLayoutId = getParentLayoutId(
942             layout.getGroupId(), layout.isPrivateLayout(), parentLayoutId);
943 
944         validateParentLayoutId(
945             layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(),
946             parentLayoutId);
947 
948         if (parentLayoutId != layout.getParentLayoutId()) {
949             int priority = getNextPriority(
950                 layout.getGroupId(), layout.isPrivateLayout(), parentLayoutId);
951 
952             layout.setPriority(priority);
953         }
954 
955         layout.setParentLayoutId(parentLayoutId);
956 
957         layoutPersistence.update(layout, false);
958 
959         return layout;
960     }
961 
962     public Layout updateParentLayoutId(
963             long groupId, boolean privateLayout, long layoutId,
964             long parentLayoutId)
965         throws PortalException, SystemException {
966 
967         parentLayoutId = getParentLayoutId(
968             groupId, privateLayout, parentLayoutId);
969 
970         validateParentLayoutId(
971             groupId, privateLayout, layoutId, parentLayoutId);
972 
973         Layout layout = layoutPersistence.findByG_P_L(
974             groupId, privateLayout, layoutId);
975 
976         if (parentLayoutId != layout.getParentLayoutId()) {
977             layout.setPriority(
978                 getNextPriority(groupId, privateLayout, parentLayoutId));
979         }
980 
981         layout.setParentLayoutId(parentLayoutId);
982 
983         layoutPersistence.update(layout, false);
984 
985         return layout;
986     }
987 
988     public Layout updatePriority(long plid, int priority)
989         throws PortalException, SystemException {
990 
991         Layout layout = layoutPersistence.findByPrimaryKey(plid);
992 
993         return updatePriority(layout, priority);
994     }
995 
996     public Layout updatePriority(
997             long groupId, boolean privateLayout, long layoutId, int priority)
998         throws PortalException, SystemException {
999 
1000        Layout layout = layoutPersistence.findByG_P_L(
1001            groupId, privateLayout, layoutId);
1002
1003        return updatePriority(layout, priority);
1004    }
1005
1006    public Layout updatePriority(Layout layout, int priority)
1007        throws SystemException {
1008
1009        if (layout.getPriority() == priority) {
1010            return layout;
1011        }
1012
1013        boolean lessThan = false;
1014
1015        if (layout.getPriority() < priority) {
1016            lessThan = true;
1017        }
1018
1019        layout.setPriority(priority);
1020
1021        layoutPersistence.update(layout, false);
1022
1023        priority = 0;
1024
1025        List<Layout> layouts = layoutPersistence.findByG_P_P(
1026            layout.getGroupId(), layout.isPrivateLayout(),
1027            layout.getParentLayoutId());
1028
1029        layouts = ListUtil.sort(
1030            layouts, new LayoutPriorityComparator(layout, lessThan));
1031
1032        for (Layout curLayout : layouts) {
1033            curLayout.setPriority(priority++);
1034
1035            layoutPersistence.update(curLayout, false);
1036
1037            if (curLayout.equals(layout)) {
1038                layout = curLayout;
1039            }
1040        }
1041
1042        return layout;
1043    }
1044
1045    protected String getFriendlyURL(String friendlyURL) {
1046        return FriendlyURLNormalizer.normalize(friendlyURL);
1047    }
1048
1049    protected String getFriendlyURL(
1050            long groupId, boolean privateLayout, long layoutId,
1051            String friendlyName, String friendlyURL)
1052        throws PortalException, SystemException {
1053
1054        friendlyURL = getFriendlyURL(friendlyURL);
1055
1056        if (Validator.isNull(friendlyURL)) {
1057            friendlyURL = StringPool.SLASH + getFriendlyURL(friendlyName);
1058
1059            String originalFriendlyURL = friendlyURL;
1060
1061            for (int i = 1;; i++) {
1062                try {
1063                    validateFriendlyURL(
1064                        groupId, privateLayout, layoutId, friendlyURL);
1065
1066                    break;
1067                }
1068                catch (LayoutFriendlyURLException lfurle) {
1069                    int type = lfurle.getType();
1070
1071                    if (type == LayoutFriendlyURLException.DUPLICATE) {
1072                        friendlyURL = originalFriendlyURL + i;
1073                    }
1074                    else {
1075                        friendlyURL = StringPool.SLASH + layoutId;
1076
1077                        break;
1078                    }
1079                }
1080            }
1081        }
1082
1083        return friendlyURL;
1084    }
1085
1086    protected int getNextPriority(
1087            long groupId, boolean privateLayout, long parentLayoutId)
1088        throws SystemException {
1089
1090        List<Layout> layouts = layoutPersistence.findByG_P_P(
1091            groupId, privateLayout, parentLayoutId);
1092
1093        if (layouts.size() == 0) {
1094            return 0;
1095        }
1096
1097        Layout layout = layouts.get(layouts.size() - 1);
1098
1099        return layout.getPriority() + 1;
1100    }
1101
1102    protected long getParentLayoutId(
1103            long groupId, boolean privateLayout, long parentLayoutId)
1104        throws SystemException {
1105
1106        if (parentLayoutId != LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
1107
1108            // Ensure parent layout exists
1109
1110            Layout parentLayout = layoutPersistence.fetchByG_P_L(
1111                groupId, privateLayout, parentLayoutId);
1112
1113            if (parentLayout == null) {
1114                parentLayoutId = LayoutConstants.DEFAULT_PARENT_LAYOUT_ID;
1115            }
1116        }
1117
1118        return parentLayoutId;
1119    }
1120
1121    protected boolean isDescendant(Layout layout, long layoutId)
1122        throws PortalException, SystemException {
1123
1124        if (layout.getLayoutId() == layoutId) {
1125            return true;
1126        }
1127        else {
1128            for (Layout childLayout : layout.getChildren()) {
1129                if (isDescendant(childLayout, layoutId)) {
1130                    return true;
1131                }
1132            }
1133
1134            return false;
1135        }
1136    }
1137
1138    protected void setLocalizedAttributes(
1139        Layout layout, Map<Locale, String> localeNamesMap,
1140        Map<Locale, String> localeTitlesMap) {
1141
1142        if (localeNamesMap == null) {
1143            return;
1144        }
1145
1146        if (localeTitlesMap == null) {
1147            return;
1148        }
1149
1150        ClassLoader portalClassLoader = PortalClassLoaderUtil.getClassLoader();
1151
1152        Thread currentThread = Thread.currentThread();
1153
1154        ClassLoader contextClassLoader = currentThread.getContextClassLoader();
1155
1156        try {
1157            if (contextClassLoader != portalClassLoader) {
1158                currentThread.setContextClassLoader(portalClassLoader);
1159            }
1160
1161            Locale[] locales = LanguageUtil.getAvailableLocales();
1162
1163            for (Locale locale : locales) {
1164                String name = localeNamesMap.get(locale);
1165                String title = localeTitlesMap.get(locale);
1166
1167                layout.setName(name, locale);
1168                layout.setTitle(title, locale);
1169            }
1170        }
1171        finally {
1172            if (contextClassLoader != portalClassLoader) {
1173                currentThread.setContextClassLoader(contextClassLoader);
1174            }
1175        }
1176    }
1177
1178    protected void validate(
1179            long groupId, boolean privateLayout, long layoutId,
1180            long parentLayoutId, String type, boolean hidden,
1181            String friendlyURL)
1182        throws PortalException, SystemException {
1183
1184        boolean firstLayout = false;
1185
1186        if (parentLayoutId == LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
1187            List<Layout> layouts = layoutPersistence.findByG_P_P(
1188                groupId, privateLayout, parentLayoutId, 0, 1);
1189
1190            if (layouts.size() == 0) {
1191                firstLayout = true;
1192            }
1193            else {
1194                long firstLayoutId = layouts.get(0).getLayoutId();
1195
1196                if (firstLayoutId == layoutId) {
1197                    firstLayout = true;
1198                }
1199            }
1200        }
1201
1202        if (firstLayout) {
1203            validateFirstLayout(type, hidden);
1204        }
1205
1206        if (!PortalUtil.isLayoutParentable(type)) {
1207            if (layoutPersistence.countByG_P_P(
1208                    groupId, privateLayout, layoutId) > 0) {
1209
1210                throw new LayoutTypeException(
1211                    LayoutTypeException.NOT_PARENTABLE);
1212            }
1213        }
1214
1215        validateFriendlyURL(groupId, privateLayout, layoutId, friendlyURL);
1216    }
1217
1218    protected void validateFirstLayout(String type, boolean hidden)
1219        throws PortalException {
1220
1221        if (!PortalUtil.isLayoutFirstPageable(type)) {
1222            throw new LayoutTypeException(LayoutTypeException.FIRST_LAYOUT);
1223        }
1224
1225        if (hidden) {
1226            throw new LayoutHiddenException();
1227        }
1228    }
1229
1230    protected void validateFriendlyURL(
1231            long groupId, boolean privateLayout, long layoutId,
1232            String friendlyURL)
1233        throws PortalException, SystemException {
1234
1235        if (Validator.isNull(friendlyURL)) {
1236            return;
1237        }
1238
1239        int exceptionType = LayoutImpl.validateFriendlyURL(friendlyURL);
1240
1241        if (exceptionType != -1) {
1242            throw new LayoutFriendlyURLException(exceptionType);
1243        }
1244
1245        Layout layout = layoutPersistence.fetchByG_P_F(
1246            groupId, privateLayout, friendlyURL);
1247
1248        if ((layout != null) && (layout.getLayoutId() != layoutId)) {
1249            throw new LayoutFriendlyURLException(
1250                LayoutFriendlyURLException.DUPLICATE);
1251        }
1252
1253        LayoutImpl.validateFriendlyURLKeyword(friendlyURL);
1254
1255        /*List<FriendlyURLMapper> friendlyURLMappers =
1256            portletLocalService.getFriendlyURLMappers();
1257
1258        for (FriendlyURLMapper friendlyURLMapper : friendlyURLMappers) {
1259            if (friendlyURL.indexOf(friendlyURLMapper.getMapping()) != -1) {
1260                LayoutFriendlyURLException lfurle =
1261                    new LayoutFriendlyURLException(
1262                        LayoutFriendlyURLException.KEYWORD_CONFLICT);
1263
1264                lfurle.setKeywordConflict(friendlyURLMapper.getMapping());
1265
1266                throw lfurle;
1267            }
1268        }*/
1269
1270        String layoutIdFriendlyURL = friendlyURL.substring(1);
1271
1272        if (Validator.isNumber(layoutIdFriendlyURL) &&
1273            !layoutIdFriendlyURL.equals(String.valueOf(layoutId))) {
1274
1275            LayoutFriendlyURLException lfurle = new LayoutFriendlyURLException(
1276                LayoutFriendlyURLException.POSSIBLE_DUPLICATE);
1277
1278            lfurle.setKeywordConflict(layoutIdFriendlyURL);
1279
1280            throw lfurle;
1281        }
1282    }
1283
1284    protected void validateParentLayoutId(
1285            long groupId, boolean privateLayout, long layoutId,
1286            long parentLayoutId)
1287        throws PortalException, SystemException {
1288
1289        Layout layout = layoutPersistence.findByG_P_L(
1290            groupId, privateLayout, layoutId);
1291
1292        if (parentLayoutId != layout.getParentLayoutId()) {
1293
1294            // Layouts can always be moved to the root level
1295
1296            if (parentLayoutId == LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
1297                return;
1298            }
1299
1300            // Layout cannot become a child of a layout that is not parentable
1301
1302            Layout parentLayout = layoutPersistence.findByG_P_L(
1303                groupId, privateLayout, parentLayoutId);
1304
1305            if (!PortalUtil.isLayoutParentable(parentLayout)) {
1306                throw new LayoutParentLayoutIdException(
1307                    LayoutParentLayoutIdException.NOT_PARENTABLE);
1308            }
1309
1310            // Layout cannot become descendant of itself
1311
1312            if (isDescendant(layout, parentLayoutId)) {
1313                throw new LayoutParentLayoutIdException(
1314                    LayoutParentLayoutIdException.SELF_DESCENDANT);
1315            }
1316
1317            // If layout is moved, the new first layout must be valid
1318
1319            if (layout.getParentLayoutId() ==
1320                    LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
1321
1322                List<Layout> layouts = layoutPersistence.findByG_P_P(
1323                    groupId, privateLayout,
1324                    LayoutConstants.DEFAULT_PARENT_LAYOUT_ID, 0, 2);
1325
1326                // You can only reach this point if there are more than two
1327                // layouts at the root level because of the descendant check
1328
1329                long firstLayoutId = layouts.get(0).getLayoutId();
1330
1331                if (firstLayoutId == layoutId) {
1332                    Layout secondLayout = layouts.get(1);
1333
1334                    try {
1335                        validateFirstLayout(
1336                            secondLayout.getType(), secondLayout.getHidden());
1337                    }
1338                    catch (LayoutHiddenException lhe) {
1339                        throw new LayoutParentLayoutIdException(
1340                            LayoutParentLayoutIdException.FIRST_LAYOUT_HIDDEN);
1341                    }
1342                    catch (LayoutTypeException lte) {
1343                        throw new LayoutParentLayoutIdException(
1344                            LayoutParentLayoutIdException.FIRST_LAYOUT_TYPE);
1345                    }
1346                }
1347            }
1348        }
1349    }
1350
1351    private static Log _log =
1352         LogFactoryUtil.getLog(LayoutLocalServiceImpl.class);
1353
1354}