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