001
014
015 package com.liferay.portal.service.impl;
016
017 import com.liferay.portal.LayoutFriendlyURLException;
018 import com.liferay.portal.LayoutFriendlyURLsException;
019 import com.liferay.portal.LayoutNameException;
020 import com.liferay.portal.LayoutParentLayoutIdException;
021 import com.liferay.portal.LayoutTypeException;
022 import com.liferay.portal.NoSuchLayoutException;
023 import com.liferay.portal.kernel.bean.BeanReference;
024 import com.liferay.portal.kernel.bean.IdentifiableBean;
025 import com.liferay.portal.kernel.exception.PortalException;
026 import com.liferay.portal.kernel.exception.SystemException;
027 import com.liferay.portal.kernel.language.LanguageUtil;
028 import com.liferay.portal.kernel.portlet.FriendlyURLMapper;
029 import com.liferay.portal.kernel.util.FriendlyURLNormalizerUtil;
030 import com.liferay.portal.kernel.util.LocaleUtil;
031 import com.liferay.portal.kernel.util.StringPool;
032 import com.liferay.portal.kernel.util.StringUtil;
033 import com.liferay.portal.kernel.util.Validator;
034 import com.liferay.portal.model.Group;
035 import com.liferay.portal.model.Layout;
036 import com.liferay.portal.model.LayoutConstants;
037 import com.liferay.portal.model.LayoutFriendlyURL;
038 import com.liferay.portal.model.LayoutSet;
039 import com.liferay.portal.model.LayoutSetPrototype;
040 import com.liferay.portal.model.ResourceConstants;
041 import com.liferay.portal.model.Role;
042 import com.liferay.portal.model.RoleConstants;
043 import com.liferay.portal.model.impl.LayoutImpl;
044 import com.liferay.portal.security.permission.ActionKeys;
045 import com.liferay.portal.service.PortletLocalServiceUtil;
046 import com.liferay.portal.service.ResourcePermissionLocalService;
047 import com.liferay.portal.service.RoleLocalServiceUtil;
048 import com.liferay.portal.service.persistence.LayoutFriendlyURLPersistence;
049 import com.liferay.portal.service.persistence.LayoutPersistence;
050 import com.liferay.portal.service.persistence.LayoutSetPersistence;
051 import com.liferay.portal.util.Portal;
052 import com.liferay.portal.util.PortalUtil;
053 import com.liferay.portal.util.comparator.LayoutPriorityComparator;
054 import com.liferay.portlet.sites.util.SitesUtil;
055
056 import java.util.HashMap;
057 import java.util.List;
058 import java.util.Locale;
059 import java.util.Map;
060
061
064 public class LayoutLocalServiceHelper implements IdentifiableBean {
065
066 @Override
067 public String getBeanIdentifier() {
068 return _beanIdentifier;
069 }
070
071 public String getFriendlyURL(
072 long groupId, boolean privateLayout, long layoutId, String name,
073 String friendlyURL)
074 throws PortalException, SystemException {
075
076 friendlyURL = getFriendlyURL(friendlyURL);
077
078 if (Validator.isNotNull(friendlyURL)) {
079 return friendlyURL;
080 }
081
082 friendlyURL = StringPool.SLASH + getFriendlyURL(name);
083
084 String originalFriendlyURL = friendlyURL;
085
086 for (int i = 1;; i++) {
087 try {
088 validateFriendlyURL(
089 groupId, privateLayout, layoutId, friendlyURL);
090
091 break;
092 }
093 catch (LayoutFriendlyURLException lfurle) {
094 int type = lfurle.getType();
095
096 if (type == LayoutFriendlyURLException.DUPLICATE) {
097 friendlyURL = originalFriendlyURL + i;
098 }
099 else {
100 friendlyURL = StringPool.SLASH + layoutId;
101
102 break;
103 }
104 }
105 }
106
107 return friendlyURL;
108 }
109
110 public String getFriendlyURL(String friendlyURL) {
111 return FriendlyURLNormalizerUtil.normalize(friendlyURL);
112 }
113
114 public Map<Locale, String> getFriendlyURLMap(
115 long groupId, boolean privateLayout, long layoutId, String name,
116 Map<Locale, String> friendlyURLMap)
117 throws PortalException, SystemException {
118
119 Map<Locale, String> newFriendlyURLMap = new HashMap<Locale, String>();
120
121 Locale[] locales = LanguageUtil.getAvailableLocales(groupId);
122
123 for (Locale locale : locales) {
124 String friendlyURL = friendlyURLMap.get(locale);
125
126 if (Validator.isNotNull(friendlyURL)) {
127 friendlyURL = getFriendlyURL(
128 groupId, privateLayout, layoutId, name, friendlyURL);
129
130 newFriendlyURLMap.put(locale, friendlyURL);
131 }
132 }
133
134 Locale siteDefaultLocale = LocaleUtil.getSiteDefault();
135
136 if (newFriendlyURLMap.isEmpty() ||
137 Validator.isNull(newFriendlyURLMap.get(siteDefaultLocale))) {
138
139 String friendlyURL = getFriendlyURL(
140 groupId, privateLayout, layoutId, name, StringPool.BLANK);
141
142 newFriendlyURLMap.put(siteDefaultLocale, friendlyURL);
143 }
144
145 return newFriendlyURLMap;
146 }
147
148 public int getNextPriority(
149 long groupId, boolean privateLayout, long parentLayoutId,
150 String sourcePrototypeLayoutUuid, int defaultPriority)
151 throws SystemException {
152
153 try {
154 int priority = defaultPriority;
155
156 if (priority < 0) {
157 Layout layout = layoutPersistence.findByG_P_P_First(
158 groupId, privateLayout, parentLayoutId,
159 new LayoutPriorityComparator(false));
160
161 priority = layout.getPriority() + 1;
162 }
163
164 if ((priority < _PRIORITY_BUFFER) &&
165 Validator.isNull(sourcePrototypeLayoutUuid)) {
166
167 LayoutSet layoutSet = layoutSetPersistence.fetchByG_P(
168 groupId, privateLayout);
169
170 if (Validator.isNotNull(
171 layoutSet.getLayoutSetPrototypeUuid()) &&
172 layoutSet.isLayoutSetPrototypeLinkEnabled()) {
173
174 priority = priority + _PRIORITY_BUFFER;
175 }
176 }
177
178 return priority;
179 }
180 catch (NoSuchLayoutException nsle) {
181 return 0;
182 }
183 }
184
185 public long getParentLayoutId(
186 long groupId, boolean privateLayout, long parentLayoutId)
187 throws SystemException {
188
189 if (parentLayoutId != LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
190
191
192
193 Layout parentLayout = layoutPersistence.fetchByG_P_L(
194 groupId, privateLayout, parentLayoutId);
195
196 if (parentLayout == null) {
197 parentLayoutId = LayoutConstants.DEFAULT_PARENT_LAYOUT_ID;
198 }
199 }
200
201 return parentLayoutId;
202 }
203
204 public boolean hasLayoutSetPrototypeLayout(
205 LayoutSetPrototype layoutSetPrototype, String layoutUuid)
206 throws PortalException, SystemException {
207
208 Layout layout = layoutPersistence.fetchByUUID_G_P(
209 layoutUuid, layoutSetPrototype.getGroupId(), true);
210
211 if (layout != null) {
212 return true;
213 }
214
215 return false;
216 }
217
218 @Override
219 public void setBeanIdentifier(String beanIdentifier) {
220 _beanIdentifier = beanIdentifier;
221 }
222
223 public void validate(
224 long groupId, boolean privateLayout, long layoutId,
225 long parentLayoutId, String name, String type, boolean hidden,
226 Map<Locale, String> friendlyURLMap)
227 throws PortalException, SystemException {
228
229 validateName(name);
230
231 boolean firstLayout = false;
232
233 if (parentLayoutId == LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
234 List<Layout> layouts = layoutPersistence.findByG_P_P(
235 groupId, privateLayout, parentLayoutId, 0, 1);
236
237 if (layouts.size() == 0) {
238 firstLayout = true;
239 }
240 else {
241 long firstLayoutId = layouts.get(0).getLayoutId();
242
243 if (firstLayoutId == layoutId) {
244 firstLayout = true;
245 }
246 }
247 }
248 else {
249
250
251
252
253 Layout parentLayout = layoutPersistence.findByG_P_L(
254 groupId, privateLayout, parentLayoutId);
255
256 if (!SitesUtil.isLayoutSortable(parentLayout)) {
257 throw new LayoutParentLayoutIdException(
258 LayoutParentLayoutIdException.NOT_SORTABLE);
259 }
260 }
261
262 if (firstLayout) {
263 validateFirstLayout(type);
264 }
265
266 if (!PortalUtil.isLayoutParentable(type)) {
267 if (layoutPersistence.countByG_P_P(
268 groupId, privateLayout, layoutId) > 0) {
269
270 throw new LayoutTypeException(
271 LayoutTypeException.NOT_PARENTABLE);
272 }
273 }
274
275 validateFriendlyURLs(groupId, privateLayout, layoutId, friendlyURLMap);
276 }
277
278 public void validateFirstLayout(Layout layout)
279 throws PortalException, SystemException {
280
281 Group group = layout.getGroup();
282
283 if (group.isGuest() && layout.isPublicLayout() &&
284 !hasGuestViewPermission(layout)) {
285
286 LayoutTypeException lte = new LayoutTypeException(
287 LayoutTypeException.FIRST_LAYOUT_PERMISSION);
288
289 throw lte;
290 }
291
292 validateFirstLayout(layout.getType());
293 }
294
295 public void validateFirstLayout(String type) throws PortalException {
296 if (Validator.isNull(type) || !PortalUtil.isLayoutFirstPageable(type)) {
297 LayoutTypeException lte = new LayoutTypeException(
298 LayoutTypeException.FIRST_LAYOUT);
299
300 lte.setLayoutType(type);
301
302 throw lte;
303 }
304 }
305
306 public void validateFriendlyURL(
307 long groupId, boolean privateLayout, long layoutId,
308 String friendlyURL)
309 throws PortalException, SystemException {
310
311 if (Validator.isNull(friendlyURL)) {
312 return;
313 }
314
315 int exceptionType = LayoutImpl.validateFriendlyURL(friendlyURL);
316
317 if (exceptionType != -1) {
318 throw new LayoutFriendlyURLException(exceptionType);
319 }
320
321 List<LayoutFriendlyURL> layoutFriendlyURLs =
322 layoutFriendlyURLPersistence.findByG_P_F(
323 groupId, privateLayout, friendlyURL);
324
325 for (LayoutFriendlyURL layoutFriendlyURL : layoutFriendlyURLs) {
326 Layout layout = layoutPersistence.findByPrimaryKey(
327 layoutFriendlyURL.getPlid());
328
329 if (layout.getLayoutId() != layoutId) {
330 throw new LayoutFriendlyURLException(
331 LayoutFriendlyURLException.DUPLICATE);
332 }
333 }
334
335 LayoutImpl.validateFriendlyURLKeyword(friendlyURL);
336
337 if (friendlyURL.contains(Portal.FRIENDLY_URL_SEPARATOR)) {
338 LayoutFriendlyURLException lfurle =
339 new LayoutFriendlyURLException(
340 LayoutFriendlyURLException.KEYWORD_CONFLICT);
341
342 lfurle.setKeywordConflict(Portal.FRIENDLY_URL_SEPARATOR);
343
344 throw lfurle;
345 }
346
347 List<FriendlyURLMapper> friendlyURLMappers =
348 PortletLocalServiceUtil.getFriendlyURLMappers();
349
350 for (FriendlyURLMapper friendlyURLMapper : friendlyURLMappers) {
351 if (friendlyURLMapper.isCheckMappingWithPrefix()) {
352 continue;
353 }
354
355 String mapping = StringPool.SLASH + friendlyURLMapper.getMapping();
356
357 if (friendlyURL.contains(mapping + StringPool.SLASH) ||
358 friendlyURL.endsWith(mapping)) {
359
360 LayoutFriendlyURLException lfurle =
361 new LayoutFriendlyURLException(
362 LayoutFriendlyURLException.KEYWORD_CONFLICT);
363
364 lfurle.setKeywordConflict(friendlyURLMapper.getMapping());
365
366 throw lfurle;
367 }
368 }
369
370 Locale[] availableLocales = LanguageUtil.getAvailableLocales();
371
372 for (Locale locale : availableLocales) {
373 String languageId = StringUtil.toLowerCase(
374 LocaleUtil.toLanguageId(locale));
375
376 String i18nPathLanguageId =
377 StringPool.SLASH +
378 PortalUtil.getI18nPathLanguageId(locale, languageId);
379
380 if (friendlyURL.startsWith(i18nPathLanguageId + StringPool.SLASH) ||
381 friendlyURL.startsWith(
382 StringPool.SLASH + languageId + StringPool.SLASH) ||
383 friendlyURL.endsWith(i18nPathLanguageId) ||
384 friendlyURL.endsWith(StringPool.SLASH + languageId)) {
385
386 LayoutFriendlyURLException lfurle =
387 new LayoutFriendlyURLException(
388 LayoutFriendlyURLException.KEYWORD_CONFLICT);
389
390 lfurle.setKeywordConflict(i18nPathLanguageId);
391
392 throw lfurle;
393 }
394 }
395
396 String layoutIdFriendlyURL = friendlyURL.substring(1);
397
398 if (Validator.isNumber(layoutIdFriendlyURL) &&
399 !layoutIdFriendlyURL.equals(String.valueOf(layoutId))) {
400
401 LayoutFriendlyURLException lfurle = new LayoutFriendlyURLException(
402 LayoutFriendlyURLException.POSSIBLE_DUPLICATE);
403
404 lfurle.setKeywordConflict(layoutIdFriendlyURL);
405
406 throw lfurle;
407 }
408 }
409
410 public void validateFriendlyURLs(
411 long groupId, boolean privateLayout, long layoutId,
412 Map<Locale, String> friendlyURLMap)
413 throws PortalException, SystemException {
414
415 LayoutFriendlyURLsException layoutFriendlyURLsException = null;
416
417 for (Map.Entry<Locale, String> entry : friendlyURLMap.entrySet()) {
418 try {
419 String friendlyURL = entry.getValue();
420
421 validateFriendlyURL(
422 groupId, privateLayout, layoutId, friendlyURL);
423 }
424 catch (LayoutFriendlyURLException lfurle) {
425 Locale locale = entry.getKey();
426
427 if (layoutFriendlyURLsException == null) {
428 layoutFriendlyURLsException =
429 new LayoutFriendlyURLsException();
430 }
431
432 layoutFriendlyURLsException.addLocalizedException(
433 locale, lfurle);
434 }
435 }
436
437 if (layoutFriendlyURLsException != null) {
438 throw layoutFriendlyURLsException;
439 }
440 }
441
442 public void validateName(String name) throws PortalException {
443 if (Validator.isNull(name)) {
444 throw new LayoutNameException();
445 }
446 }
447
448 public void validateName(String name, String languageId)
449 throws PortalException {
450
451 String defaultLanguageId = LocaleUtil.toLanguageId(
452 LocaleUtil.getSiteDefault());
453
454 if (defaultLanguageId.equals(languageId)) {
455 validateName(name);
456 }
457 }
458
459 public void validateParentLayoutId(
460 long groupId, boolean privateLayout, long layoutId,
461 long parentLayoutId)
462 throws PortalException, SystemException {
463
464 Layout layout = layoutPersistence.findByG_P_L(
465 groupId, privateLayout, layoutId);
466
467 if (parentLayoutId == layout.getParentLayoutId()) {
468 return;
469 }
470
471
472
473 if (parentLayoutId == LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
474 return;
475 }
476
477
478
479 Layout parentLayout = layoutPersistence.findByG_P_L(
480 groupId, privateLayout, parentLayoutId);
481
482 if (!PortalUtil.isLayoutParentable(parentLayout)) {
483 throw new LayoutParentLayoutIdException(
484 LayoutParentLayoutIdException.NOT_PARENTABLE);
485 }
486
487
488
489
490 if (!SitesUtil.isLayoutSortable(parentLayout)) {
491 throw new LayoutParentLayoutIdException(
492 LayoutParentLayoutIdException.NOT_SORTABLE);
493 }
494
495
496
497 if (PortalUtil.isLayoutDescendant(layout, parentLayoutId)) {
498 throw new LayoutParentLayoutIdException(
499 LayoutParentLayoutIdException.SELF_DESCENDANT);
500 }
501
502
503
504 if (layout.getParentLayoutId() ==
505 LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
506
507 List<Layout> layouts = layoutPersistence.findByG_P_P(
508 groupId, privateLayout,
509 LayoutConstants.DEFAULT_PARENT_LAYOUT_ID, 0, 2);
510
511
512
513
514 long firstLayoutId = layouts.get(0).getLayoutId();
515
516 if (firstLayoutId == layoutId) {
517 Layout secondLayout = layouts.get(1);
518
519 if (Validator.isNull(secondLayout.getType()) ||
520 !PortalUtil.isLayoutFirstPageable(secondLayout.getType())) {
521
522 throw new LayoutParentLayoutIdException(
523 LayoutParentLayoutIdException.FIRST_LAYOUT_TYPE);
524 }
525 }
526 }
527 }
528
529 protected boolean hasGuestViewPermission(Layout layout)
530 throws PortalException, SystemException {
531
532 Role role = RoleLocalServiceUtil.getRole(
533 layout.getCompanyId(), RoleConstants.GUEST);
534
535 return resourcePermissionLocalService.hasResourcePermission(
536 layout.getCompanyId(), Layout.class.getName(),
537 ResourceConstants.SCOPE_INDIVIDUAL,
538 String.valueOf(layout.getPlid()), role.getRoleId(),
539 ActionKeys.VIEW);
540 }
541
542 @BeanReference(type = LayoutFriendlyURLPersistence.class)
543 protected LayoutFriendlyURLPersistence layoutFriendlyURLPersistence;
544
545 @BeanReference(type = LayoutPersistence.class)
546 protected LayoutPersistence layoutPersistence;
547
548 @BeanReference(type = LayoutSetPersistence.class)
549 protected LayoutSetPersistence layoutSetPersistence;
550
551 @BeanReference(type = ResourcePermissionLocalService.class)
552 protected ResourcePermissionLocalService resourcePermissionLocalService;
553
554 private static final int _PRIORITY_BUFFER = 1000000;
555
556 private String _beanIdentifier;
557
558 }