1 17 package org.alfresco.repo.security.permissions.impl; 18 19 import java.io.Serializable ; 20 import java.util.HashSet ; 21 import java.util.List ; 22 import java.util.Set ; 23 24 import net.sf.acegisecurity.Authentication; 25 import net.sf.acegisecurity.GrantedAuthority; 26 import net.sf.acegisecurity.providers.dao.User; 27 28 import org.alfresco.repo.cache.SimpleCache; 29 import org.alfresco.repo.security.authentication.AuthenticationComponent; 30 import org.alfresco.repo.security.permissions.DynamicAuthority; 31 import org.alfresco.repo.security.permissions.NodePermissionEntry; 32 import org.alfresco.repo.security.permissions.PermissionEntry; 33 import org.alfresco.repo.security.permissions.PermissionReference; 34 import org.alfresco.repo.security.permissions.PermissionServiceSPI; 35 import org.alfresco.service.cmr.dictionary.DictionaryService; 36 import org.alfresco.service.cmr.repository.ChildAssociationRef; 37 import org.alfresco.service.cmr.repository.NodeRef; 38 import org.alfresco.service.cmr.repository.NodeService; 39 import org.alfresco.service.cmr.security.AccessPermission; 40 import org.alfresco.service.cmr.security.AccessStatus; 41 import org.alfresco.service.cmr.security.AuthorityService; 42 import org.alfresco.service.cmr.security.AuthorityType; 43 import org.alfresco.service.cmr.security.PermissionService; 44 import org.alfresco.service.namespace.QName; 45 import org.alfresco.util.EqualsHelper; 46 import org.apache.commons.logging.Log; 47 import org.apache.commons.logging.LogFactory; 48 import org.springframework.beans.factory.InitializingBean; 49 50 56 public class PermissionServiceImpl implements PermissionServiceSPI, InitializingBean 57 { 58 59 static SimplePermissionReference OLD_ALL_PERMISSIONS_REFERENCE = new SimplePermissionReference( 60 QName.createQName("", PermissionService.ALL_PERMISSIONS), 61 PermissionService.ALL_PERMISSIONS); 62 63 private static Log log = LogFactory.getLog(PermissionServiceImpl.class); 64 65 66 private SimpleCache<Serializable , AccessStatus> accessCache; 67 68 71 private ModelDAO modelDAO; 72 73 76 private PermissionsDAO permissionsDAO; 77 78 81 private NodeService nodeService; 82 83 86 private DictionaryService dictionaryService; 87 88 91 private AuthenticationComponent authenticationComponent; 92 93 96 private AuthorityService authorityService; 97 98 101 private List <DynamicAuthority> dynamicAuthorities; 102 103 106 public PermissionServiceImpl() 107 { 108 super(); 109 } 110 111 115 public void setDictionaryService(DictionaryService dictionaryService) 116 { 117 this.dictionaryService = dictionaryService; 118 } 119 120 public void setModelDAO(ModelDAO modelDAO) 121 { 122 this.modelDAO = modelDAO; 123 } 124 125 public void setNodeService(NodeService nodeService) 126 { 127 this.nodeService = nodeService; 128 } 129 130 public void setPermissionsDAO(PermissionsDAO permissionsDAO) 131 { 132 this.permissionsDAO = permissionsDAO; 133 } 134 135 public void setAuthenticationComponent(AuthenticationComponent authenticationComponent) 136 { 137 this.authenticationComponent = authenticationComponent; 138 } 139 140 public void setAuthorityService(AuthorityService authorityService) 141 { 142 this.authorityService = authorityService; 143 } 144 145 public void setDynamicAuthorities(List <DynamicAuthority> dynamicAuthorities) 146 { 147 this.dynamicAuthorities = dynamicAuthorities; 148 } 149 150 155 public void setAccessCache(SimpleCache<Serializable , AccessStatus> accessCache) 156 { 157 this.accessCache = accessCache; 158 } 159 160 public void afterPropertiesSet() throws Exception 161 { 162 if (dictionaryService == null) 163 { 164 throw new IllegalArgumentException ("Property 'dictionaryService' has not been set"); 165 } 166 if (modelDAO == null) 167 { 168 throw new IllegalArgumentException ("Property 'modelDAO' has not been set"); 169 } 170 if (nodeService == null) 171 { 172 throw new IllegalArgumentException ("Property 'nodeService' has not been set"); 173 } 174 if (permissionsDAO == null) 175 { 176 throw new IllegalArgumentException ("Property 'permissionsDAO' has not been set"); 177 } 178 if (authenticationComponent == null) 179 { 180 throw new IllegalArgumentException ("Property 'authenticationComponent' has not been set"); 181 } 182 if(authorityService == null) 183 { 184 throw new IllegalArgumentException ("Property 'authorityService' has not been set"); 185 } 186 if (accessCache == null) 187 { 188 throw new IllegalArgumentException ("Property 'accessCache' has not been set"); 189 } 190 } 191 192 196 public String getOwnerAuthority() 197 { 198 return OWNER_AUTHORITY; 199 } 200 201 public String getAllAuthorities() 202 { 203 return ALL_AUTHORITIES; 204 } 205 206 public String getAllPermission() 207 { 208 return ALL_PERMISSIONS; 209 } 210 211 public Set <AccessPermission> getPermissions(NodeRef nodeRef) 212 { 213 return getAllPermissionsImpl(nodeRef, true, true); 214 } 215 216 public Set <AccessPermission> getAllSetPermissions(NodeRef nodeRef) 217 { 218 HashSet <AccessPermission> accessPermissions = new HashSet <AccessPermission>(); 219 NodePermissionEntry nodePremissionEntry = getSetPermissions(nodeRef); 220 for (PermissionEntry pe : nodePremissionEntry.getPermissionEntries()) 221 { 222 accessPermissions.add(new AccessPermissionImpl(getPermission(pe.getPermissionReference()), pe 223 .getAccessStatus(), pe.getAuthority())); 224 } 225 return accessPermissions; 226 } 227 228 private Set <AccessPermission> getAllPermissionsImpl(NodeRef nodeRef, boolean includeTrue, boolean includeFalse) 229 { 230 String userName = authenticationComponent.getCurrentUserName(); 231 HashSet <AccessPermission> accessPermissions = new HashSet <AccessPermission>(); 232 for (PermissionReference pr : getSettablePermissionReferences(nodeRef)) 233 { 234 if (hasPermission(nodeRef, pr) == AccessStatus.ALLOWED) 235 { 236 accessPermissions.add(new AccessPermissionImpl(getPermission(pr), AccessStatus.ALLOWED, userName)); 237 } 238 else 239 { 240 if (includeFalse) 241 { 242 accessPermissions.add(new AccessPermissionImpl(getPermission(pr), AccessStatus.DENIED, userName)); 243 } 244 } 245 } 246 return accessPermissions; 247 } 248 249 private class AccessPermissionImpl implements AccessPermission 250 { 251 private String permission; 252 253 private AccessStatus accessStatus; 254 255 private String authority; 256 257 private AuthorityType authorityType; 258 259 AccessPermissionImpl(String permission, AccessStatus accessStatus, String authority) 260 { 261 this.permission = permission; 262 this.accessStatus = accessStatus; 263 this.authority = authority; 264 this.authorityType = AuthorityType.getAuthorityType(authority); 265 } 266 267 public String getPermission() 268 { 269 return permission; 270 } 271 272 public AccessStatus getAccessStatus() 273 { 274 return accessStatus; 275 } 276 277 public String getAuthority() 278 { 279 return authority; 280 } 281 282 public AuthorityType getAuthorityType() 283 { 284 return authorityType; 285 } 286 287 @Override 288 public boolean equals(Object o) 289 { 290 if (this == o) 291 { 292 return true; 293 } 294 if (!(o instanceof AccessPermissionImpl)) 295 { 296 return false; 297 } 298 AccessPermissionImpl other = (AccessPermissionImpl) o; 299 return this.getPermission().equals(other.getPermission()) 300 && (this.getAccessStatus() == other.getAccessStatus() && (this.getAccessStatus().equals(other 301 .getAccessStatus()))); 302 } 303 304 @Override 305 public int hashCode() 306 { 307 return ((authority.hashCode() * 37) + permission.hashCode()) * 37 + accessStatus.hashCode(); 308 } 309 } 310 311 public Set <String > getSettablePermissions(NodeRef nodeRef) 312 { 313 Set <PermissionReference> settable = getSettablePermissionReferences(nodeRef); 314 Set <String > strings = new HashSet <String >(settable.size()); 315 for (PermissionReference pr : settable) 316 { 317 strings.add(getPermission(pr)); 318 } 319 return strings; 320 } 321 322 public Set <String > getSettablePermissions(QName type) 323 { 324 Set <PermissionReference> settable = getSettablePermissionReferences(type); 325 Set <String > strings = new HashSet <String >(settable.size()); 326 for (PermissionReference pr : settable) 327 { 328 strings.add(getPermission(pr)); 329 } 330 return strings; 331 } 332 333 public NodePermissionEntry getSetPermissions(NodeRef nodeRef) 334 { 335 return permissionsDAO.getPermissions(nodeRef); 336 } 337 338 public AccessStatus hasPermission(NodeRef nodeRef, PermissionReference perm) 339 { 340 if (nodeRef == null) 344 { 345 return AccessStatus.ALLOWED; 346 } 347 348 if (perm == null) 350 { 351 return AccessStatus.DENIED; 352 } 353 354 if (!nodeService.exists(nodeRef)) 356 { 357 return AccessStatus.ALLOWED; 358 } 359 360 Authentication auth = authenticationComponent.getCurrentAuthentication(); 363 Set <String > authorisations = getAuthorisations(auth, nodeRef); 364 Serializable key = generateKey( 365 authorisations, 366 nodeRef, 367 perm); 368 AccessStatus status = accessCache.get(key); 369 if (status != null) 370 { 371 return status; 372 } 373 374 Set <PermissionReference> available = modelDAO.getAllPermissions(nodeRef); 377 available.add(getAllPermissionReference()); 378 available.add(OLD_ALL_PERMISSIONS_REFERENCE); 379 380 if (!(available.contains(perm))) 381 { 382 accessCache.put(key, AccessStatus.DENIED); 383 return AccessStatus.DENIED; 384 } 385 386 390 394 395 QName typeQname = nodeService.getType(nodeRef); 396 Set <QName> aspectQNames = nodeService.getAspects(nodeRef); 397 398 if (perm.equals(OLD_ALL_PERMISSIONS_REFERENCE)) 399 { 400 perm = getAllPermissionReference(); 401 } 402 NodeTest nt = new NodeTest(perm, typeQname, aspectQNames); 403 boolean result = nt.evaluate(authorisations, nodeRef); 404 if (log.isDebugEnabled()) 405 { 406 log.debug("Permission <" 407 + perm + "> is " + (result ? "allowed" : "denied") + " for " 408 + authenticationComponent.getCurrentUserName() + " on node " + nodeService.getPath(nodeRef)); 409 } 410 411 status = result ? AccessStatus.ALLOWED : AccessStatus.DENIED; 412 accessCache.put(key, status); 413 return status; 414 } 415 416 421 static Serializable generateKey(Set <String > auths, NodeRef ref, PermissionReference perm) 422 { 423 HashSet <Serializable > key = new HashSet <Serializable >(auths); 424 key.add(ref.getId()); 425 key.add(perm.toString()); 426 return key; 427 } 428 429 435 private Set <String > getAuthorisations(Authentication auth, NodeRef nodeRef) 436 { 437 HashSet <String > auths = new HashSet <String >(); 438 if (auth == null) 440 { 441 return auths; 442 } 443 User user = (User) auth.getPrincipal(); 445 auths.add(user.getUsername()); 446 for (GrantedAuthority authority : auth.getAuthorities()) 447 { 448 auths.add(authority.getAuthority()); 449 } 450 if (dynamicAuthorities != null) 451 { 452 for (DynamicAuthority da : dynamicAuthorities) 453 { 454 if (da.hasAuthority(nodeRef, user.getUsername())) 455 { 456 auths.add(da.getAuthority()); 457 } 458 } 459 } 460 auths.addAll(authorityService.getAuthorities()); 461 return auths; 462 } 463 464 public NodePermissionEntry explainPermission(NodeRef nodeRef, PermissionReference perm) 465 { 466 return null; 468 } 469 470 public void deletePermissions(NodeRef nodeRef) 471 { 472 permissionsDAO.deletePermissions(nodeRef); 473 accessCache.clear(); 474 } 475 476 public void deletePermissions(NodePermissionEntry nodePermissionEntry) 477 { 478 permissionsDAO.deletePermissions(nodePermissionEntry); 479 accessCache.clear(); 480 } 481 482 public void deletePermission(PermissionEntry permissionEntry) 483 { 484 permissionsDAO.deletePermissions(permissionEntry); 485 accessCache.clear(); 486 } 487 488 public void deletePermission(NodeRef nodeRef, String authority, PermissionReference perm, boolean allow) 489 { 490 permissionsDAO.deletePermissions(nodeRef, authority, perm, allow); 491 accessCache.clear(); 492 } 493 494 public void clearPermission(NodeRef nodeRef, String authority) 495 { 496 permissionsDAO.clearPermission(nodeRef, authority); 497 accessCache.clear(); 498 } 499 500 public void setPermission(NodeRef nodeRef, String authority, PermissionReference perm, boolean allow) 501 { 502 permissionsDAO.setPermission(nodeRef, authority, perm, allow); 503 accessCache.clear(); 504 } 505 506 public void setPermission(PermissionEntry permissionEntry) 507 { 508 permissionsDAO.setPermission(permissionEntry); 509 accessCache.clear(); 510 } 511 512 public void setPermission(NodePermissionEntry nodePermissionEntry) 513 { 514 permissionsDAO.setPermission(nodePermissionEntry); 515 accessCache.clear(); 516 } 517 518 public void setInheritParentPermissions(NodeRef nodeRef, boolean inheritParentPermissions) 519 { 520 permissionsDAO.setInheritParentPermissions(nodeRef, inheritParentPermissions); 521 accessCache.clear(); 522 } 523 524 527 public boolean getInheritParentPermissions(NodeRef nodeRef) 528 { 529 return permissionsDAO.getInheritParentPermissions(nodeRef); 530 } 531 532 533 public PermissionReference getPermissionReference(QName qname, String permissionName) 534 { 535 return modelDAO.getPermissionReference(qname, permissionName); 536 } 537 538 public PermissionReference getAllPermissionReference() 539 { 540 return getPermissionReference(ALL_PERMISSIONS); 541 } 542 543 public String getPermission(PermissionReference permissionReference) 544 { 545 if (modelDAO.isUnique(permissionReference)) 546 { 547 return permissionReference.getName(); 548 } 549 else 550 { 551 return permissionReference.toString(); 552 } 553 } 554 555 public PermissionReference getPermissionReference(String permissionName) 556 { 557 return modelDAO.getPermissionReference(null, permissionName); 558 } 559 560 public Set <PermissionReference> getSettablePermissionReferences(QName type) 561 { 562 return modelDAO.getExposedPermissions(type); 563 } 564 565 public Set <PermissionReference> getSettablePermissionReferences(NodeRef nodeRef) 566 { 567 return modelDAO.getExposedPermissions(nodeRef); 568 } 569 570 public void deletePermission(NodeRef nodeRef, String authority, String perm, boolean allow) 571 { 572 deletePermission(nodeRef, authority, getPermissionReference(perm), allow); 573 } 574 575 public AccessStatus hasPermission(NodeRef nodeRef, String perm) 576 { 577 return hasPermission(nodeRef, getPermissionReference(perm)); 578 } 579 580 public void setPermission(NodeRef nodeRef, String authority, String perm, boolean allow) 581 { 582 setPermission(nodeRef, authority, getPermissionReference(perm), allow); 583 } 584 585 public void deletePermissions(String recipient) 586 { 587 permissionsDAO.deleteAllPermissionsForAuthority(recipient); 588 accessCache.clear(); 589 } 590 591 595 600 private class NodeTest 601 { 602 605 PermissionReference required; 606 607 610 Set <PermissionReference> granters; 611 612 615 Set <PermissionReference> nodeRequirements = new HashSet <PermissionReference>(); 616 617 620 Set <PermissionReference> parentRequirements = new HashSet <PermissionReference>(); 621 622 625 Set <PermissionReference> childrenRequirements = new HashSet <PermissionReference>(); 626 627 630 QName typeQName; 631 632 635 Set <QName> aspectQNames; 636 637 640 NodeTest(PermissionReference required, QName typeQName, Set <QName> aspectQNames) 641 { 642 this.required = required; 643 this.typeQName = typeQName; 644 this.aspectQNames = aspectQNames; 645 646 nodeRequirements = modelDAO.getRequiredPermissions(required, typeQName, aspectQNames, 648 RequiredPermission.On.NODE); 649 650 parentRequirements = modelDAO.getRequiredPermissions(required, typeQName, aspectQNames, 651 RequiredPermission.On.PARENT); 652 653 childrenRequirements = modelDAO.getRequiredPermissions(required, typeQName, aspectQNames, 654 RequiredPermission.On.CHILDREN); 655 656 granters = modelDAO.getGrantingPermissions(required); 659 granters.add(getAllPermissionReference()); 660 granters.add(OLD_ALL_PERMISSIONS_REFERENCE); 661 } 662 663 670 boolean evaluate(Set <String > authorisations, NodeRef nodeRef) 671 { 672 Set <Pair<String , PermissionReference>> denied = new HashSet <Pair<String , PermissionReference>>(); 673 return evaluate(authorisations, nodeRef, denied, null); 674 } 675 676 685 boolean evaluate(Set <String > authorisations, NodeRef nodeRef, Set <Pair<String , PermissionReference>> denied, 686 MutableBoolean recursiveIn) 687 { 688 MutableBoolean recursiveOut = null; 690 691 Set <Pair<String , PermissionReference>> locallyDenied = new HashSet <Pair<String , PermissionReference>>(); 692 locallyDenied.addAll(denied); 693 locallyDenied.addAll(getDenied(nodeRef)); 694 695 boolean success = true; 697 698 if (required.equals(getPermissionReference(ALL_PERMISSIONS)) || modelDAO.checkPermission(required)) 701 { 702 if (parentRequirements.contains(required)) 703 { 704 if (checkGlobalPermissions(authorisations) || checkRequired(authorisations, nodeRef, locallyDenied)) 705 { 706 recursiveOut = null; 708 if (recursiveIn != null) 709 { 710 recursiveIn.setValue(true); 711 } 712 } 713 else 714 { 715 recursiveOut = new MutableBoolean(false); 718 } 719 } 720 else 721 { 722 success &= hasSinglePermission(authorisations, nodeRef); 724 } 725 if (!success) 726 { 727 return false; 728 } 729 } 730 731 for (PermissionReference pr : nodeRequirements) 733 { 734 NodeTest nt = new NodeTest(pr, typeQName, aspectQNames); 736 success &= nt.evaluate(authorisations, nodeRef, locallyDenied, null); 737 if (!success) 738 { 739 return false; 740 } 741 } 742 743 745 if (success) 746 { 747 ChildAssociationRef car = nodeService.getPrimaryParent(nodeRef); 748 if (car.getParentRef() != null) 749 { 750 751 NodePermissionEntry nodePermissions = permissionsDAO.getPermissions(car.getChildRef()); 752 if ((nodePermissions == null) || (nodePermissions.inheritPermissions())) 753 { 754 755 locallyDenied.addAll(getDenied(car.getParentRef())); 756 for (PermissionReference pr : parentRequirements) 757 { 758 if (pr.equals(required)) 759 { 760 success &= this.evaluate(authorisations, car.getParentRef(), locallyDenied, 762 recursiveOut); 763 if ((recursiveOut != null) && recursiveOut.getValue()) 764 { 765 if (recursiveIn != null) 766 { 767 recursiveIn.setValue(true); 768 } 769 } 770 } 771 else 772 { 773 NodeTest nt = new NodeTest(pr, typeQName, aspectQNames); 774 success &= nt.evaluate(authorisations, car.getParentRef(), locallyDenied, null); 775 } 776 777 if (!success) 778 { 779 return false; 780 } 781 } 782 } 783 } 784 } 785 786 if ((recursiveOut != null) && (!recursiveOut.getValue())) 787 { 788 return false; 790 } 791 792 if (childrenRequirements.size() > 0) 794 { 795 List <ChildAssociationRef> childAssocRefs = nodeService.getChildAssocs(nodeRef); 796 for (PermissionReference pr : childrenRequirements) 797 { 798 for (ChildAssociationRef child : childAssocRefs) 799 { 800 success &= (hasPermission(child.getChildRef(), pr) == AccessStatus.ALLOWED); 801 if (!success) 802 { 803 return false; 804 } 805 } 806 } 807 } 808 809 return success; 810 } 811 812 public boolean hasSinglePermission(Set <String > authorisations, NodeRef nodeRef) 813 { 814 816 if (checkGlobalPermissions(authorisations)) 817 { 818 return true; 819 } 820 821 Set <Pair<String , PermissionReference>> denied = new HashSet <Pair<String , PermissionReference>>(); 822 823 825 ChildAssociationRef car = nodeService.getPrimaryParent(nodeRef); 828 while (car != null) 830 { 831 839 denied.addAll(getDenied(car.getChildRef())); 840 841 if (checkRequired(authorisations, car.getChildRef(), denied)) 844 { 845 return true; 846 } 847 848 if (car.getParentRef() != null) 850 { 851 NodePermissionEntry nodePermissions = permissionsDAO.getPermissions(car.getChildRef()); 852 if ((nodePermissions == null) || (nodePermissions.inheritPermissions())) 853 { 854 car = nodeService.getPrimaryParent(car.getParentRef()); 855 } 856 else 857 { 858 car = null; 859 } 860 } 861 else 862 { 863 car = null; 864 } 865 866 } 867 868 870 return false; 871 872 } 873 874 880 private boolean checkGlobalPermissions(Set <String > authorisations) 881 { 882 for (PermissionEntry pe : modelDAO.getGlobalPermissionEntries()) 883 { 884 if (isGranted(pe, authorisations, null)) 885 { 886 return true; 887 } 888 } 889 return false; 890 } 891 892 898 Set <Pair<String , PermissionReference>> getDenied(NodeRef nodeRef) 899 { 900 Set <Pair<String , PermissionReference>> deniedSet = new HashSet <Pair<String , PermissionReference>>(); 901 902 NodePermissionEntry nodeEntry = permissionsDAO.getPermissions(nodeRef); 904 if (nodeEntry != null) 905 { 906 for (PermissionEntry pe : nodeEntry.getPermissionEntries()) 907 { 908 if (pe.isDenied()) 909 { 910 Set <PermissionReference> granters = modelDAO 914 .getGrantingPermissions(pe.getPermissionReference()); 915 for (PermissionReference granter : granters) 916 { 917 deniedSet.add(new Pair<String , PermissionReference>(pe.getAuthority(), granter)); 918 } 919 920 Set <PermissionReference> grantees = modelDAO.getGranteePermissions(pe.getPermissionReference()); 923 for (PermissionReference grantee : grantees) 924 { 925 deniedSet.add(new Pair<String , PermissionReference>(pe.getAuthority(), grantee)); 926 } 927 928 if (pe.getPermissionReference().equals(getAllPermissionReference()) || pe.getPermissionReference().equals(OLD_ALL_PERMISSIONS_REFERENCE)) 931 { 932 for (PermissionReference deny : modelDAO.getAllPermissions(nodeRef)) 933 { 934 deniedSet.add(new Pair<String , PermissionReference>(pe.getAuthority(), deny)); 935 } 936 } 937 } 938 } 939 } 940 return deniedSet; 941 } 942 943 951 boolean checkRequired(Set <String > authorisations, NodeRef nodeRef, Set <Pair<String , PermissionReference>> denied) 952 { 953 NodePermissionEntry nodeEntry = permissionsDAO.getPermissions(nodeRef); 954 955 if (nodeEntry == null) 957 { 958 return false; 959 } 960 961 for (PermissionEntry pe : nodeEntry.getPermissionEntries()) 964 { 965 if (isGranted(pe, authorisations, denied)) 966 { 967 return true; 968 } 969 } 970 return false; 971 } 972 973 986 private boolean isGranted(PermissionEntry pe, Set <String > authorisations, 987 Set <Pair<String , PermissionReference>> denied) 988 { 989 if (pe.isDenied()) 991 { 992 return false; 993 } 994 995 if (denied != null) 998 { 999 Pair<String , PermissionReference> specific = new Pair<String , PermissionReference>(pe.getAuthority(), 1000 required); 1001 if (denied.contains(specific)) 1002 { 1003 return false; 1004 } 1005 } 1006 1007 if (authorisations.contains(pe.getAuthority()) && granters.contains(pe.getPermissionReference())) 1011 { 1012 { 1013 return true; 1014 } 1015 } 1016 1017 return false; 1019 } 1020 1021 } 1022 1023 1028 private static class Pair<A, B> 1029 { 1030 A a; 1031 1032 B b; 1033 1034 Pair(A a, B b) 1035 { 1036 this.a = a; 1037 this.b = b; 1038 } 1039 1040 A getA() 1041 { 1042 return a; 1043 } 1044 1045 B getB() 1046 { 1047 return b; 1048 } 1049 1050 @Override 1051 public boolean equals(Object o) 1052 { 1053 if (this == o) 1054 { 1055 return true; 1056 } 1057 if (!(this instanceof Pair)) 1058 { 1059 return false; 1060 } 1061 Pair other = (Pair) o; 1062 return EqualsHelper.nullSafeEquals(this.getA(), other.getA()) 1063 && EqualsHelper.nullSafeEquals(this.getB(), other.getB()); 1064 } 1065 1066 @Override 1067 public int hashCode() 1068 { 1069 return (((a == null) ? 0 : a.hashCode()) * 37) + ((b == null) ? 0 : b.hashCode()); 1070 } 1071 1072 } 1073 1074 private static class MutableBoolean 1075 { 1076 private boolean value; 1077 1078 MutableBoolean(boolean value) 1079 { 1080 this.value = value; 1081 } 1082 1083 void setValue(boolean value) 1084 { 1085 this.value = value; 1086 } 1087 1088 boolean getValue() 1089 { 1090 return value; 1091 } 1092 } 1093} 1094 | Popular Tags |