001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing,
013     * software distributed under the License is distributed on an
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     * KIND, either express or implied.  See the License for the
016     * specific language governing permissions and limitations
017     * under the License.
018     */
019    package org.apache.shiro.authz.permission;
020    
021    import org.apache.shiro.util.StringUtils;
022    
023    import java.util.Set;
024    
025    /**
026     * Provides a base Permission class from which type-safe/domain-specific subclasses may extend.  Can be used
027     * as a base class for JPA/Hibernate persisted permissions that wish to store the parts of the permission string
028     * in separate columns (e.g. 'domain', 'actions' and 'targets' columns), which can be used in querying
029     * strategies.
030     *
031     * @since 1.0
032     */
033    public class DomainPermission extends WildcardPermission {
034    
035        private String domain;
036        private Set<String> actions;
037        private Set<String> targets;
038    
039        private static final long serialVersionUID = 1l;
040    
041        /**
042         * Creates a domain permission with *all* actions for *all* targets;
043         */
044        public DomainPermission() {
045            this.domain = getDomain(getClass());
046            setParts(getDomain(getClass()));
047        }
048    
049        public DomainPermission(String actions) {
050            domain = getDomain(getClass());
051            this.actions = StringUtils.splitToSet(actions, SUBPART_DIVIDER_TOKEN);
052            encodeParts(domain, actions, null);
053        }
054    
055        public DomainPermission(String actions, String targets) {
056            this.domain = getDomain(getClass());
057            this.actions = StringUtils.splitToSet(actions, SUBPART_DIVIDER_TOKEN);
058            this.targets = StringUtils.splitToSet(targets, SUBPART_DIVIDER_TOKEN);
059            encodeParts(this.domain, actions, targets);
060        }
061    
062        protected DomainPermission(Set<String> actions, Set<String> targets) {
063            this.domain = getDomain(getClass());
064            setParts(domain, actions, targets);
065        }
066    
067        private void encodeParts(String domain, String actions, String targets) {
068            if (!StringUtils.hasText(domain)) {
069                throw new IllegalArgumentException("domain argument cannot be null or empty.");
070            }
071            StringBuilder sb = new StringBuilder(domain);
072    
073            if (!StringUtils.hasText(actions)) {
074                if (StringUtils.hasText(targets)) {
075                    sb.append(PART_DIVIDER_TOKEN).append(WILDCARD_TOKEN);
076                }
077            } else {
078                sb.append(PART_DIVIDER_TOKEN).append(actions);
079            }
080            if (StringUtils.hasText(targets)) {
081                sb.append(PART_DIVIDER_TOKEN).append(targets);
082            }
083            setParts(sb.toString());
084        }
085    
086        protected void setParts(String domain, Set<String> actions, Set<String> targets) {
087            String actionsString = StringUtils.toDelimitedString(actions, SUBPART_DIVIDER_TOKEN);
088            String targetsString = StringUtils.toDelimitedString(targets, SUBPART_DIVIDER_TOKEN);
089            encodeParts(domain, actionsString, targetsString);
090            this.domain = domain;
091            this.actions = actions;
092            this.targets = targets;
093        }
094    
095        protected String getDomain(Class<? extends DomainPermission> clazz) {
096            String domain = clazz.getSimpleName().toLowerCase();
097            //strip any trailing 'permission' text from the name (as all subclasses should have been named):
098            int index = domain.lastIndexOf("permission");
099            if (index != -1) {
100                domain = domain.substring(0, index);
101            }
102            return domain;
103        }
104    
105        public String getDomain() {
106            return domain;
107        }
108    
109        protected void setDomain(String domain) {
110            if (this.domain != null && this.domain.equals(domain)) {
111                return;
112            }
113            this.domain = domain;
114            setParts(domain, actions, targets);
115        }
116    
117        public Set<String> getActions() {
118            return actions;
119        }
120    
121        protected void setActions(Set<String> actions) {
122            if (this.actions != null && this.actions.equals(actions)) {
123                return;
124            }
125            this.actions = actions;
126            setParts(domain, actions, targets);
127        }
128    
129        public Set<String> getTargets() {
130            return targets;
131        }
132    
133        protected void setTargets(Set<String> targets) {
134            this.targets = targets;
135            if (this.targets != null && this.targets.equals(targets)) {
136                return;
137            }
138            this.targets = targets;
139            setParts(domain, actions, targets);
140        }
141    }