2 * Copyright (C) 2012 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
9 package eu
.etaxonomy
.cdm
.persistence
.hibernate
.permission
;
11 import java
.util
.EnumSet
;
12 import java
.util
.UUID
;
13 import java
.util
.regex
.Matcher
;
14 import java
.util
.regex
.Pattern
;
16 import org
.apache
.log4j
.Logger
;
17 import org
.springframework
.security
.access
.ConfigAttribute
;
18 import org
.springframework
.security
.core
.GrantedAuthority
;
20 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
21 import eu
.etaxonomy
.cdm
.model
.common
.GrantedAuthorityImpl
;
23 import sun
.security
.provider
.PolicyParser
.ParsingException
;
26 * A <code>CdmAuthority</code> consists basically of two parts which are separated
27 * by a dot character '.'.
30 * <li><code>permissionClass</code>: an {@link CdmPermissionClass} instance with represents a cdm
31 * type or a part of the cdm type hierarchy. The className is always represented
32 * as an upper case string.</li>
33 * <li><code>property</code>: The <code>CdmAuthority</code> only applies to instances
34 * which satisfy the specified property. Interpretation is up to type specific voters.</li>
35 * <li><code>operation</code>: a string which specifies a {@link Operation} on that set of cdm
37 * <li><code>targetUuid</code>: The <code>operation</code> may be restricted to a specific cdm entity by adding
38 * the entity uuid to the <code>operation</code>. The uuid string is enclosed in curly brackets '<code>{</code>'
39 * , '<code>}</code>' and appended to the end of the <code>operation</code>.</li>
42 * <h3>Examples for permissionStrings</h3>
49 * DESCRIPTIONBASE.UPDATE
50 * DESCRIPTIONELEMENTBASE(Ecology).UPDATE
51 * TAXONNODE.UPDATE{20c8f083-5870-4cbd-bf56-c5b2b98ab6a7}
54 * The method {@link #getPermissionString(String)} parses a full authority and returns permissionString and
55 * the {@link CdmAuthority} from the <code>authority</code>.
60 public class CdmAuthority
implements GrantedAuthority
, ConfigAttribute
, IGrantedAuthorityConverter
{
62 private static final long serialVersionUID
= 1L;
64 public static final Logger logger
= Logger
.getLogger(CdmAuthority
.class);
66 CdmPermissionClass permissionClass
;
68 EnumSet
<CRUD
> operation
;
71 public CdmAuthority(CdmBase targetDomainObject
, EnumSet
<CRUD
> operation
, UUID uuid
){
72 this.permissionClass
= CdmPermissionClass
.getValueOf(targetDomainObject
);
74 this.operation
= operation
;
75 this.targetUuid
= uuid
;
78 public CdmAuthority(CdmBase targetDomainObject
, String property
, EnumSet
<CRUD
> operation
, UUID uuid
){
79 this.permissionClass
= CdmPermissionClass
.getValueOf(targetDomainObject
);
80 this.property
= property
;
81 this.operation
= operation
;
82 this.targetUuid
= uuid
;
86 public CdmAuthority(CdmPermissionClass permissionClass
, String property
, EnumSet
<CRUD
> operation
, UUID uuid
){
87 this.permissionClass
= permissionClass
;
88 this.property
= property
;
89 this.operation
= operation
;
90 this.targetUuid
= uuid
;
93 private CdmAuthority (String authority
) throws ParsingException
{
95 String
[] tokens
= parse(authority
);
96 // className must never be null
97 permissionClass
= CdmPermissionClass
.valueOf(tokens
[0]);
99 if(tokens
[2] != null){
101 operation
= Operation
.fromString(tokens
[2]);
102 } catch (IllegalArgumentException e
) {
103 logger
.warn("cannot parse Operation " + tokens
[2]);
107 if(tokens
[3] != null){
108 targetUuid
= UUID
.fromString(tokens
[3]);
112 public CdmPermissionClass
getPermissionClass(){
113 return permissionClass
;
116 public String
getProperty(){
120 public EnumSet
<CRUD
> getOperation(){
124 public UUID
getTargetUUID(){
128 public boolean hasTargetUuid() {
129 return targetUuid
!= null;
132 public boolean hasProperty() {
133 return property
!= null;
137 * Parses the given <code>authority</code> and returns an array of tokens.
138 * The array has a length of four elements whereas the elements can be null.
139 * The elements in the array correspond to the fields of {@link CdmAuthority}:
141 * <li>{@link CdmAuthority#permissionClass}</li>
142 * <li>{@link CdmAuthority#property}</li>
143 * <li>{@link CdmAuthority#operation}</li>
144 * <li>{@link CdmAuthority#targetUuid}</li>
147 * @return an array of tokens
148 * @throws ParsingException
150 protected String
[] parse(String authority
) throws ParsingException
{
152 // regex pattern explained:
153 // (\\w*) -> classname
154 // (?:\\((\\w*)\\))? -> (property)
156 // (?:(\\w*))(?:\\{([\\da-z\\-]+)\\})? -> Permmission and targetUuid
158 String regex
= "(\\w*)(?:\\((\\w*)\\))?\\.?(?:(\\w*))(?:\\{([\\da-z\\-]+)\\})?";
159 Pattern pattern
= Pattern
.compile(regex
);
160 String
[] tokens
= new String
[4];
161 logger
.debug("parsing '" + authority
+ "'");
162 Matcher m
= pattern
.matcher(authority
);
164 if (m
.find() && m
.groupCount() == 4 ) {
165 for (int i
= 0; i
< m
.groupCount(); i
++) {
166 tokens
[i
] = m
.group(i
+1);
167 // normalize empty strings to null
168 if(tokens
[i
] != null && tokens
[i
].length() == 0){
171 logger
.debug("[" + i
+ "]: " + tokens
[i
]+ "\n");
174 logger
.debug("no match");
175 throw new ParsingException("Unsupported authority string: '" + authority
+ "'");
184 * same as {@link #toString()} and {@link #getAttribute()}
187 public String
getAuthority() {
194 * same as {@link #toString()} and {@link #getAuthority()}
197 public String
getAttribute() {
202 public String
toString() {
203 StringBuilder sb
= new StringBuilder();
204 sb
.append(permissionClass
.toString());
205 if(property
!= null){
206 sb
.append('(').append(property
).append(')');
208 sb
.append('.').append(operation
.toString());
209 if(targetUuid
!= null){
210 sb
.append('{').append(targetUuid
.toString()).append('}');
212 return sb
.toString() ;
216 * Constructs a new CdmAuthority by parsing the authority string.
217 * For details on the syntax please refer to the class
218 * documentation above.
222 * @throws ParsingException
224 public static CdmAuthority
fromGrantedAuthority(GrantedAuthority authority
) throws ParsingException
{
225 return new CdmAuthority(authority
.getAuthority());
229 * @see eu.etaxonomy.cdm.persistence.hibernate.permission.IGrantedAuthorityConverter#asNewGrantedAuthority()
232 public GrantedAuthorityImpl
asNewGrantedAuthority() throws ParsingException
{
233 GrantedAuthorityImpl grantedAuthority
= GrantedAuthorityImpl
.NewInstance();
234 grantedAuthority
.setAuthority(getAuthority());
235 return grantedAuthority
;