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