001
014
015 package com.liferay.portal.service.impl;
016
017 import com.liferay.portal.ResourceActionsException;
018 import com.liferay.portal.kernel.bean.BeanPropertiesUtil;
019 import com.liferay.portal.kernel.exception.PortalException;
020 import com.liferay.portal.kernel.exception.SystemException;
021 import com.liferay.portal.kernel.log.Log;
022 import com.liferay.portal.kernel.log.LogFactoryUtil;
023 import com.liferay.portal.kernel.search.SearchEngineUtil;
024 import com.liferay.portal.kernel.util.ListUtil;
025 import com.liferay.portal.model.AuditedModel;
026 import com.liferay.portal.model.GroupedModel;
027 import com.liferay.portal.model.PermissionedModel;
028 import com.liferay.portal.model.Resource;
029 import com.liferay.portal.model.ResourceConstants;
030 import com.liferay.portal.model.ResourcePermission;
031 import com.liferay.portal.model.Role;
032 import com.liferay.portal.model.RoleConstants;
033 import com.liferay.portal.model.impl.ResourceImpl;
034 import com.liferay.portal.security.permission.PermissionCacheUtil;
035 import com.liferay.portal.security.permission.PermissionThreadLocal;
036 import com.liferay.portal.security.permission.ResourceActionsUtil;
037 import com.liferay.portal.service.ServiceContext;
038 import com.liferay.portal.service.base.ResourceLocalServiceBaseImpl;
039 import com.liferay.portal.util.ResourcePermissionsThreadLocal;
040
041 import java.util.Arrays;
042 import java.util.Iterator;
043 import java.util.List;
044
045 import org.apache.commons.lang.time.StopWatch;
046
047
099 public class ResourceLocalServiceImpl extends ResourceLocalServiceBaseImpl {
100
101
146 @Override
147 public void addModelResources(
148 AuditedModel auditedModel, ServiceContext serviceContext)
149 throws PortalException, SystemException {
150
151 if (serviceContext.isAddGroupPermissions() ||
152 serviceContext.isAddGuestPermissions()) {
153
154 addResources(
155 auditedModel.getCompanyId(), getGroupId(auditedModel),
156 auditedModel.getUserId(), auditedModel.getModelClassName(),
157 String.valueOf(auditedModel.getPrimaryKeyObj()), false,
158 serviceContext.isAddGroupPermissions(),
159 serviceContext.isAddGuestPermissions(),
160 getPermissionedModel(auditedModel));
161 }
162 else {
163 if (serviceContext.isDeriveDefaultPermissions()) {
164 serviceContext.deriveDefaultPermissions(
165 getGroupId(auditedModel), auditedModel.getModelClassName());
166 }
167
168 addModelResources(
169 auditedModel.getCompanyId(), getGroupId(auditedModel),
170 auditedModel.getUserId(), auditedModel.getModelClassName(),
171 String.valueOf(auditedModel.getPrimaryKeyObj()),
172 serviceContext.getGroupPermissions(),
173 serviceContext.getGuestPermissions(),
174 getPermissionedModel(auditedModel));
175 }
176 }
177
178
196 @Override
197 public void addModelResources(
198 long companyId, long groupId, long userId, String name,
199 long primKey, String[] groupPermissions, String[] guestPermissions)
200 throws PortalException, SystemException {
201
202 addModelResources(
203 companyId, groupId, userId, name, String.valueOf(primKey),
204 groupPermissions, guestPermissions, null);
205 }
206
207
225 @Override
226 public void addModelResources(
227 long companyId, long groupId, long userId, String name,
228 String primKey, String[] groupPermissions,
229 String[] guestPermissions)
230 throws PortalException, SystemException {
231
232 addModelResources(
233 companyId, groupId, userId, name, primKey, groupPermissions,
234 guestPermissions, null);
235 }
236
237
258 @Override
259 public void addResources(
260 long companyId, long groupId, long userId, String name,
261 long primKey, boolean portletActions, boolean addGroupPermissions,
262 boolean addGuestPermissions)
263 throws PortalException, SystemException {
264
265 addResources(
266 companyId, groupId, userId, name, String.valueOf(primKey),
267 portletActions, addGroupPermissions, addGuestPermissions, null);
268 }
269
270
291 @Override
292 public void addResources(
293 long companyId, long groupId, long userId, String name,
294 String primKey, boolean portletActions, boolean addGroupPermissions,
295 boolean addGuestPermissions)
296 throws PortalException, SystemException {
297
298 addResources(
299 companyId, groupId, userId, name, primKey, portletActions,
300 addGroupPermissions, addGuestPermissions, null);
301 }
302
303
317 @Override
318 public void addResources(
319 long companyId, long groupId, String name, boolean portletActions)
320 throws PortalException, SystemException {
321
322 addResources(
323 companyId, groupId, 0, name, null, portletActions, false, false);
324 }
325
326
335 @Override
336 public void deleteResource(AuditedModel auditedModel, int scope)
337 throws PortalException, SystemException {
338
339 deleteResource(
340 auditedModel.getCompanyId(), auditedModel.getModelClassName(),
341 scope, String.valueOf(auditedModel.getPrimaryKeyObj()),
342 getPermissionedModel(auditedModel));
343 }
344
345
357 @Override
358 public void deleteResource(
359 long companyId, String name, int scope, long primKey)
360 throws PortalException, SystemException {
361
362 deleteResource(companyId, name, scope, String.valueOf(primKey), null);
363 }
364
365
377 @Override
378 public void deleteResource(
379 long companyId, String name, int scope, String primKey)
380 throws PortalException, SystemException {
381
382 deleteResource(companyId, name, scope, primKey, null);
383 }
384
385
396 @Override
397 public Resource getResource(
398 long companyId, String name, int scope, String primKey) {
399
400 Resource resource = new ResourceImpl();
401
402 resource.setCompanyId(companyId);
403 resource.setName(name);
404 resource.setScope(scope);
405 resource.setPrimKey(primKey);
406
407 return resource;
408 }
409
410
430 @Override
431 public boolean hasUserPermissions(
432 long userId, long resourceId, List<Resource> resources,
433 String actionId, long[] roleIds)
434 throws PortalException, SystemException {
435
436 StopWatch stopWatch = new StopWatch();
437
438 stopWatch.start();
439
440 int block = 1;
441
442 boolean hasUserPermissions =
443 resourcePermissionLocalService.hasResourcePermission(
444 resources, roleIds, actionId);
445
446 logHasUserPermissions(userId, resourceId, actionId, stopWatch, block++);
447
448 return hasUserPermissions;
449 }
450
451
461 @Override
462 public void updateModelResources(
463 AuditedModel auditedModel, ServiceContext serviceContext)
464 throws PortalException, SystemException {
465
466 updateResources(
467 auditedModel.getCompanyId(), getGroupId(auditedModel),
468 auditedModel.getModelClassName(),
469 String.valueOf(auditedModel.getPrimaryKeyObj()),
470 serviceContext.getGroupPermissions(),
471 serviceContext.getGuestPermissions(),
472 getPermissionedModel(auditedModel));
473 }
474
475
489 @Override
490 public void updateResources(
491 long companyId, long groupId, String name, long primKey,
492 String[] groupPermissions, String[] guestPermissions)
493 throws PortalException, SystemException {
494
495 updateResources(
496 companyId, groupId, name, String.valueOf(primKey), groupPermissions,
497 guestPermissions, null);
498 }
499
500
514 @Override
515 public void updateResources(
516 long companyId, long groupId, String name, String primKey,
517 String[] groupPermissions, String[] guestPermissions)
518 throws PortalException, SystemException {
519
520 updateResources(
521 companyId, groupId, name, primKey, groupPermissions,
522 guestPermissions, null);
523 }
524
525
539 @Override
540 public void updateResources(
541 long companyId, String name, int scope, String primKey,
542 String newPrimKey)
543 throws SystemException {
544
545 if (resourceBlockLocalService.isSupported(name)) {
546
547
548
549
550
551 }
552 else {
553 updateResourcePermissions(
554 companyId, name, scope, primKey, newPrimKey);
555 }
556 }
557
558 protected void addGroupPermissions(
559 long companyId, long groupId, long userId, String name,
560 Resource resource, boolean portletActions,
561 PermissionedModel permissionedModel)
562 throws PortalException, SystemException {
563
564 List<String> actions = null;
565
566 if (portletActions) {
567 actions = ResourceActionsUtil.getPortletResourceGroupDefaultActions(
568 name);
569 }
570 else {
571 actions = ResourceActionsUtil.getModelResourceGroupDefaultActions(
572 name);
573 }
574
575 String[] actionIds = actions.toArray(new String[actions.size()]);
576
577 if (resourceBlockLocalService.isSupported(name)) {
578 addGroupPermissionsBlocks(
579 groupId, resource, actions, permissionedModel);
580 }
581 else {
582 addGroupPermissions(groupId, resource, actionIds);
583 }
584 }
585
586 protected void addGroupPermissions(
587 long groupId, Resource resource, String[] actionIds)
588 throws PortalException, SystemException {
589
590 Role role = roleLocalService.getDefaultGroupRole(groupId);
591
592 resourcePermissionLocalService.setResourcePermissions(
593 resource.getCompanyId(), resource.getName(), resource.getScope(),
594 resource.getPrimKey(), role.getRoleId(), actionIds);
595 }
596
597 protected void addGroupPermissionsBlocks(
598 long groupId, Resource resource, List<String> actionIds,
599 PermissionedModel permissionedModel)
600 throws PortalException, SystemException {
601
602 if (permissionedModel == null) {
603 throw new IllegalArgumentException("Permissioned model is null");
604 }
605
606
607
608 Role role = roleLocalService.getDefaultGroupRole(groupId);
609
610 resourceBlockLocalService.setIndividualScopePermissions(
611 resource.getCompanyId(), groupId, resource.getName(),
612 permissionedModel, role.getRoleId(), actionIds);
613 }
614
615 protected void addGuestPermissions(
616 long companyId, long groupId, long userId, String name,
617 Resource resource, boolean portletActions,
618 PermissionedModel permissionedModel)
619 throws PortalException, SystemException {
620
621 List<String> actions = null;
622
623 if (portletActions) {
624 actions = ResourceActionsUtil.getPortletResourceGuestDefaultActions(
625 name);
626 }
627 else {
628 actions = ResourceActionsUtil.getModelResourceGuestDefaultActions(
629 name);
630 }
631
632 String[] actionIds = actions.toArray(new String[actions.size()]);
633
634 if (resourceBlockLocalService.isSupported(name)) {
635 addGuestPermissionsBlocks(
636 companyId, groupId, resource, actions, permissionedModel);
637 }
638 else {
639 addGuestPermissions(companyId, resource, actionIds);
640 }
641 }
642
643 protected void addGuestPermissions(
644 long companyId, Resource resource, String[] actionIds)
645 throws PortalException, SystemException {
646
647 Role guestRole = roleLocalService.getRole(
648 companyId, RoleConstants.GUEST);
649
650 resourcePermissionLocalService.setResourcePermissions(
651 resource.getCompanyId(), resource.getName(), resource.getScope(),
652 resource.getPrimKey(), guestRole.getRoleId(), actionIds);
653 }
654
655 protected void addGuestPermissionsBlocks(
656 long companyId, long groupId, Resource resource,
657 List<String> actionIds, PermissionedModel permissionedModel)
658 throws PortalException, SystemException {
659
660 if (permissionedModel == null) {
661 throw new IllegalArgumentException("Permissioned model is null");
662 }
663
664
665
666 Role guestRole = roleLocalService.getRole(
667 companyId, RoleConstants.GUEST);
668
669 resourceBlockLocalService.setIndividualScopePermissions(
670 resource.getCompanyId(), groupId, resource.getName(),
671 permissionedModel, guestRole.getRoleId(), actionIds);
672 }
673
674 protected void addModelResources(
675 long companyId, long groupId, long userId, Resource resource,
676 String[] groupPermissions, String[] guestPermissions,
677 PermissionedModel permissionedModel)
678 throws PortalException, SystemException {
679
680
681
682 Role ownerRole = roleLocalService.getRole(
683 companyId, RoleConstants.OWNER);
684
685 List<String> ownerActionIds =
686 ResourceActionsUtil.getModelResourceActions(resource.getName());
687
688 ownerActionIds = ListUtil.copy(ownerActionIds);
689
690 filterOwnerActions(resource.getName(), ownerActionIds);
691
692 String[] ownerPermissions = ownerActionIds.toArray(
693 new String[ownerActionIds.size()]);
694
695
696
697 Role defaultGroupRole = null;
698
699 if (groupId > 0) {
700 defaultGroupRole = roleLocalService.getDefaultGroupRole(groupId);
701
702 if (groupPermissions == null) {
703 groupPermissions = new String[0];
704 }
705 }
706
707
708
709 Role guestRole = roleLocalService.getRole(
710 companyId, RoleConstants.GUEST);
711
712 if (guestPermissions == null) {
713 guestPermissions = new String[0];
714 }
715
716 if (resourceBlockLocalService.isSupported(resource.getName())) {
717 if (permissionedModel == null) {
718 throw new IllegalArgumentException(
719 "Permissioned model is null");
720 }
721
722
723
724 resourceBlockLocalService.setIndividualScopePermissions(
725 resource.getCompanyId(), groupId, resource.getName(),
726 permissionedModel, ownerRole.getRoleId(), ownerActionIds);
727
728 if (groupId > 0) {
729 resourceBlockLocalService.setIndividualScopePermissions(
730 resource.getCompanyId(), groupId, resource.getName(),
731 permissionedModel, defaultGroupRole.getRoleId(),
732 Arrays.asList(groupPermissions));
733 }
734
735 resourceBlockLocalService.setIndividualScopePermissions(
736 resource.getCompanyId(), groupId, resource.getName(),
737 permissionedModel, guestRole.getRoleId(),
738 Arrays.asList(guestPermissions));
739 }
740 else {
741 resourcePermissionLocalService.setOwnerResourcePermissions(
742 resource.getCompanyId(), resource.getName(),
743 resource.getScope(), resource.getPrimKey(),
744 ownerRole.getRoleId(), userId, ownerPermissions);
745
746 if (groupId > 0) {
747 resourcePermissionLocalService.setResourcePermissions(
748 resource.getCompanyId(), resource.getName(),
749 resource.getScope(), resource.getPrimKey(),
750 defaultGroupRole.getRoleId(), groupPermissions);
751 }
752
753 resourcePermissionLocalService.setResourcePermissions(
754 resource.getCompanyId(), resource.getName(),
755 resource.getScope(), resource.getPrimKey(),
756 guestRole.getRoleId(), guestPermissions);
757 }
758 }
759
760 protected void addModelResources(
761 long companyId, long groupId, long userId, String name,
762 String primKey, String[] groupPermissions,
763 String[] guestPermissions, PermissionedModel permissionedModel)
764 throws PortalException, SystemException {
765
766 if (!PermissionThreadLocal.isAddResource()) {
767 return;
768 }
769
770 validate(name, false);
771
772 if (primKey == null) {
773 return;
774 }
775
776
777
778 Resource resource = getResource(
779 companyId, name, ResourceConstants.SCOPE_INDIVIDUAL, primKey);
780
781
782
783 boolean flushEnabled = PermissionThreadLocal.isFlushEnabled();
784
785 PermissionThreadLocal.setIndexEnabled(false);
786
787 try {
788 addModelResources(
789 companyId, groupId, userId, resource, groupPermissions,
790 guestPermissions, permissionedModel);
791 }
792 finally {
793 PermissionThreadLocal.setIndexEnabled(flushEnabled);
794
795 PermissionCacheUtil.clearCache();
796
797 SearchEngineUtil.updatePermissionFields(name, primKey);
798 }
799 }
800
801 protected void addResources(
802 long companyId, long groupId, long userId, Resource resource,
803 boolean portletActions, PermissionedModel permissionedModel)
804 throws PortalException, SystemException {
805
806 List<String> actionIds = null;
807
808 if (portletActions) {
809 actionIds = ResourceActionsUtil.getPortletResourceActions(
810 resource.getName());
811 }
812 else {
813 actionIds = ResourceActionsUtil.getModelResourceActions(
814 resource.getName());
815
816 actionIds = ListUtil.copy(actionIds);
817
818 filterOwnerActions(resource.getName(), actionIds);
819 }
820
821 Role role = roleLocalService.getRole(companyId, RoleConstants.OWNER);
822
823 if (resourceBlockLocalService.isSupported(resource.getName())) {
824 if (permissionedModel == null) {
825 throw new IllegalArgumentException(
826 "Permissioned model is null");
827 }
828
829
830
831 resourceBlockLocalService.setIndividualScopePermissions(
832 resource.getCompanyId(), groupId, resource.getName(),
833 permissionedModel, role.getRoleId(), actionIds);
834 }
835 else {
836 resourcePermissionLocalService.setOwnerResourcePermissions(
837 resource.getCompanyId(), resource.getName(),
838 resource.getScope(), resource.getPrimKey(), role.getRoleId(),
839 userId, actionIds.toArray(new String[actionIds.size()]));
840 }
841 }
842
843 protected void addResources(
844 long companyId, long groupId, long userId, String name,
845 String primKey, boolean portletActions, boolean addGroupPermissions,
846 boolean addGuestPermissions, PermissionedModel permissionedModel)
847 throws PortalException, SystemException {
848
849 if (!PermissionThreadLocal.isAddResource()) {
850 return;
851 }
852
853 validate(name, portletActions);
854
855 if (primKey == null) {
856 return;
857 }
858
859
860
861 Resource resource = getResource(
862 companyId, name, ResourceConstants.SCOPE_INDIVIDUAL, primKey);
863
864
865
866 boolean flushEnabled = PermissionThreadLocal.isFlushEnabled();
867
868 PermissionThreadLocal.setIndexEnabled(false);
869
870 List<ResourcePermission> resourcePermissions =
871 resourcePermissionPersistence.findByC_N_S_P(
872 companyId, name, ResourceConstants.SCOPE_INDIVIDUAL, primKey);
873
874 ResourcePermissionsThreadLocal.setResourcePermissions(
875 resourcePermissions);
876
877 try {
878 addResources(
879 companyId, groupId, userId, resource, portletActions,
880 permissionedModel);
881
882
883
884 if ((groupId > 0) && addGroupPermissions) {
885 addGroupPermissions(
886 companyId, groupId, userId, name, resource, portletActions,
887 permissionedModel);
888 }
889
890
891
892 if (addGuestPermissions) {
893
894
895
896
897 addGuestPermissions(
898 companyId, groupId, userId, name, resource, portletActions,
899 permissionedModel);
900 }
901 }
902 finally {
903 ResourcePermissionsThreadLocal.setResourcePermissions(null);
904
905 PermissionThreadLocal.setIndexEnabled(flushEnabled);
906
907 PermissionCacheUtil.clearCache();
908
909 SearchEngineUtil.updatePermissionFields(name, primKey);
910 }
911 }
912
913 protected void deleteResource(
914 long companyId, String name, int scope, String primKey,
915 PermissionedModel permissionedModel)
916 throws PortalException, SystemException {
917
918 if (resourceBlockLocalService.isSupported(name)) {
919 if (permissionedModel == null) {
920 throw new IllegalArgumentException(
921 "Permissioned model is null");
922 }
923
924 resourceBlockLocalService.releasePermissionedModelResourceBlock(
925 permissionedModel);
926
927 return;
928 }
929
930 resourcePermissionLocalService.deleteResourcePermissions(
931 companyId, name, scope, primKey);
932 }
933
934 protected void filterOwnerActions(String name, List<String> actionIds) {
935 List<String> defaultOwnerActions =
936 ResourceActionsUtil.getModelResourceOwnerDefaultActions(name);
937
938 if (defaultOwnerActions.isEmpty()) {
939 return;
940 }
941
942 Iterator<String> itr = actionIds.iterator();
943
944 while (itr.hasNext()) {
945 String actionId = itr.next();
946
947 if (!defaultOwnerActions.contains(actionId)) {
948 itr.remove();
949 }
950 }
951 }
952
953 protected long getGroupId(AuditedModel auditedModel) {
954 long groupId = 0;
955
956 if (auditedModel instanceof GroupedModel) {
957 GroupedModel groupedModel = (GroupedModel)auditedModel;
958
959 groupId = BeanPropertiesUtil.getLongSilent(
960 groupedModel, "resourceGroupId", groupedModel.getGroupId());
961 }
962
963 return groupId;
964 }
965
966 protected PermissionedModel getPermissionedModel(
967 AuditedModel auditedModel) {
968
969 PermissionedModel permissionedModel = null;
970
971 if (auditedModel instanceof PermissionedModel) {
972 permissionedModel = (PermissionedModel)auditedModel;
973 }
974
975 return permissionedModel;
976 }
977
978 protected void logHasUserPermissions(
979 long userId, long resourceId, String actionId, StopWatch stopWatch,
980 int block) {
981
982 if (!_log.isDebugEnabled()) {
983 return;
984 }
985
986 _log.debug(
987 "Checking user permissions block " + block + " for " + userId +
988 " " + resourceId + " " + actionId + " takes " +
989 stopWatch.getTime() + " ms");
990 }
991
992 protected void updateResourceBlocks(
993 long companyId, long groupId, Resource resource,
994 String[] groupPermissions, String[] guestPermissions,
995 PermissionedModel permissionedModel)
996 throws PortalException, SystemException {
997
998 if (permissionedModel == null) {
999 throw new IllegalArgumentException("Permissioned model is null");
1000 }
1001
1002
1003
1004 Role role = roleLocalService.getDefaultGroupRole(groupId);
1005
1006 resourceBlockLocalService.setIndividualScopePermissions(
1007 companyId, groupId, resource.getName(), permissionedModel,
1008 role.getRoleId(), Arrays.asList(groupPermissions));
1009
1010 role = roleLocalService.getRole(companyId, RoleConstants.GUEST);
1011
1012 resourceBlockLocalService.setIndividualScopePermissions(
1013 companyId, groupId, resource.getName(), permissionedModel,
1014 role.getRoleId(), Arrays.asList(guestPermissions));
1015 }
1016
1017 protected void updateResourcePermissions(
1018 long companyId, long groupId, Resource resource,
1019 String[] groupPermissions, String[] guestPermissions)
1020 throws PortalException, SystemException {
1021
1022 Role role = roleLocalService.getDefaultGroupRole(groupId);
1023
1024 resourcePermissionLocalService.setResourcePermissions(
1025 resource.getCompanyId(), resource.getName(), resource.getScope(),
1026 resource.getPrimKey(), role.getRoleId(), groupPermissions);
1027
1028 role = roleLocalService.getRole(companyId, RoleConstants.GUEST);
1029
1030 resourcePermissionLocalService.setResourcePermissions(
1031 resource.getCompanyId(), resource.getName(), resource.getScope(),
1032 resource.getPrimKey(), role.getRoleId(), guestPermissions);
1033 }
1034
1035 protected void updateResourcePermissions(
1036 long companyId, String name, int scope, String primKey,
1037 String newPrimKey)
1038 throws SystemException {
1039
1040 List<ResourcePermission> resourcePermissions =
1041 resourcePermissionLocalService.getResourcePermissions(
1042 companyId, name, scope, primKey);
1043
1044 for (ResourcePermission resourcePermission : resourcePermissions) {
1045 resourcePermission.setPrimKey(newPrimKey);
1046
1047 resourcePermissionPersistence.update(resourcePermission);
1048 }
1049 }
1050
1051 protected void updateResources(
1052 long companyId, long groupId, String name, String primKey,
1053 String[] groupPermissions, String[] guestPermissions,
1054 PermissionedModel permissionedModel)
1055 throws PortalException, SystemException {
1056
1057 Resource resource = getResource(
1058 companyId, name, ResourceConstants.SCOPE_INDIVIDUAL, primKey);
1059
1060 if (groupPermissions == null) {
1061 groupPermissions = new String[0];
1062 }
1063
1064 if (guestPermissions == null) {
1065 guestPermissions = new String[0];
1066 }
1067
1068 if (resourceBlockLocalService.isSupported(name)) {
1069 updateResourceBlocks(
1070 companyId, groupId, resource, groupPermissions,
1071 guestPermissions, permissionedModel);
1072 }
1073 else {
1074 updateResourcePermissions(
1075 companyId, groupId, resource, groupPermissions,
1076 guestPermissions);
1077 }
1078 }
1079
1080 protected void validate(String name, boolean portletActions)
1081 throws PortalException {
1082
1083 List<String> actions = null;
1084
1085 if (portletActions) {
1086 actions = ResourceActionsUtil.getPortletResourceActions(name);
1087 }
1088 else {
1089 actions = ResourceActionsUtil.getModelResourceActions(name);
1090 }
1091
1092 if (actions.size() == 0) {
1093 throw new ResourceActionsException(
1094 "There are no actions associated with the resource " + name);
1095 }
1096 }
1097
1098 private static Log _log = LogFactoryUtil.getLog(
1099 ResourceLocalServiceImpl.class);
1100
1101 }