View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.shiro.subject;
20  
21  import org.apache.shiro.util.CollectionUtils;
22  
23  import java.util.*;
24  
25  /**
26   * Default implementation of the {@link PrincipalMap} interface.
27   *
28   * *EXPERIMENTAL for Shiro 1.2 - DO NOT USE YET*
29   *
30   * @author Les Hazlewood
31   * @since 1.2
32   */
33  public class SimplePrincipalMap implements PrincipalMap {
34  
35      //Key: realm name, Value: map of principals specific to that realm
36      //                        internal map - key: principal name, value: principal
37      private Map<String, Map<String, Object>> realmPrincipals;
38  
39      //maintains the principals from all realms plus any that are modified via the Map modification methods
40      //this ensures a fast lookup of any named principal instead of needing to iterate over
41      //the realmPrincipals for each lookup.
42      private Map<String, Object> combinedPrincipals;
43  
44      public SimplePrincipalMap() {
45          this(null);
46      }
47  
48      public SimplePrincipalMap(Map<String, Map<String, Object>> backingMap) {
49          if (!CollectionUtils.isEmpty(backingMap)) {
50              this.realmPrincipals = backingMap;
51              for (Map<String, Object> principals : this.realmPrincipals.values()) {
52                  if (!CollectionUtils.isEmpty(principals) ) {
53                      ensureCombinedPrincipals().putAll(principals);
54                  }
55              }
56          }
57      }
58  
59      public int size() {
60          return CollectionUtils.size(this.combinedPrincipals);
61      }
62  
63      protected Map<String, Object> ensureCombinedPrincipals() {
64          if (this.combinedPrincipals == null) {
65              this.combinedPrincipals = new HashMap<String, Object>();
66          }
67          return this.combinedPrincipals;
68      }
69  
70      public boolean containsKey(Object o) {
71          return this.combinedPrincipals != null && this.combinedPrincipals.containsKey(o);
72      }
73  
74      public boolean containsValue(Object o) {
75          return this.combinedPrincipals != null && this.combinedPrincipals.containsKey(o);
76      }
77  
78      public Object get(Object o) {
79          return this.combinedPrincipals != null && this.combinedPrincipals.containsKey(o);
80      }
81  
82      public Object put(String s, Object o) {
83          return ensureCombinedPrincipals().put(s, o);
84      }
85  
86      public Object remove(Object o) {
87          return this.combinedPrincipals != null ? this.combinedPrincipals.remove(o) : null;
88      }
89  
90      public void putAll(Map<? extends String, ?> map) {
91          if (!CollectionUtils.isEmpty(map)) {
92              ensureCombinedPrincipals().putAll(map);
93          }
94      }
95  
96      public Set<String> keySet() {
97          return CollectionUtils.isEmpty(this.combinedPrincipals) ?
98                  Collections.<String>emptySet() :
99                  Collections.unmodifiableSet(this.combinedPrincipals.keySet());
100     }
101 
102     public Collection<Object> values() {
103         return CollectionUtils.isEmpty(this.combinedPrincipals) ?
104                 Collections.emptySet() :
105                 Collections.unmodifiableCollection(this.combinedPrincipals.values());
106     }
107 
108     public Set<Entry<String, Object>> entrySet() {
109         return CollectionUtils.isEmpty(this.combinedPrincipals) ?
110                 Collections.<Entry<String,Object>>emptySet() :
111                 Collections.unmodifiableSet(this.combinedPrincipals.entrySet());
112     }
113 
114     public void clear() {
115         this.realmPrincipals = null;
116         this.combinedPrincipals = null;
117     }
118 
119     public Object getPrimaryPrincipal() {
120         //heuristic - just use the first one we come across:
121         return !CollectionUtils.isEmpty(this.combinedPrincipals) ?
122                 this.combinedPrincipals.values().iterator().next() :
123                 null;
124     }
125 
126     public <T> T oneByType(Class<T> type) {
127         if (CollectionUtils.isEmpty(this.combinedPrincipals)) {
128             return null;
129         }
130         for( Object value : this.combinedPrincipals.values()) {
131             if (type.isInstance(value) ) {
132                 return type.cast(value);
133             }
134         }
135         return null;
136     }
137 
138     public <T> Collection<T> byType(Class<T> type) {
139         if (CollectionUtils.isEmpty(this.combinedPrincipals)) {
140             return Collections.emptySet();
141         }
142         Collection<T> instances = null;
143         for( Object value : this.combinedPrincipals.values()) {
144             if (type.isInstance(value) ) {
145                 if (instances == null) {
146                     instances = new ArrayList<T>();
147                 }
148                 instances.add(type.cast(value));
149             }
150         }
151         return instances != null ? instances : Collections.<T>emptyList();
152     }
153 
154     public List asList() {
155         if (CollectionUtils.isEmpty(this.combinedPrincipals)) {
156             return Collections.emptyList();
157         }
158         List<Object> list = new ArrayList<Object>(this.combinedPrincipals.size());
159         list.addAll(this.combinedPrincipals.values());
160         return list;
161     }
162 
163     public Set asSet() {
164         if (CollectionUtils.isEmpty(this.combinedPrincipals)) {
165             return Collections.emptySet();
166         }
167         Set<Object> set = new HashSet<Object>(this.combinedPrincipals.size());
168         set.addAll(this.combinedPrincipals.values());
169         return set;
170     }
171 
172     public Collection fromRealm(String realmName) {
173         if (CollectionUtils.isEmpty(this.realmPrincipals)) {
174             return Collections.emptySet();
175         }
176         Map<String,Object> principals = this.realmPrincipals.get(realmName);
177         if (CollectionUtils.isEmpty(principals)) {
178             return Collections.emptySet();
179         }
180         return Collections.unmodifiableCollection(principals.values());
181     }
182 
183     public Set<String> getRealmNames() {
184         if (CollectionUtils.isEmpty(this.realmPrincipals)) {
185             return Collections.emptySet();
186         }
187         return Collections.unmodifiableSet(this.realmPrincipals.keySet());
188     }
189 
190     public boolean isEmpty() {
191         return CollectionUtils.isEmpty(this.combinedPrincipals);
192     }
193 
194     public Iterator iterator() {
195         return asList().iterator();
196     }
197 
198     public Map<String, Object> getRealmPrincipals(String name) {
199         if (this.realmPrincipals == null) {
200             return null;
201         }
202         Map<String,Object> principals = this.realmPrincipals.get(name);
203         if (principals == null) {
204             return null;
205         }
206         return Collections.unmodifiableMap(principals);
207     }
208 
209     public Map<String,Object> setRealmPrincipals(String realmName, Map<String, Object> principals) {
210         if (realmName == null) {
211             throw new NullPointerException("realmName argument cannot be null.");
212         }
213         if (this.realmPrincipals == null) {
214             if (!CollectionUtils.isEmpty(principals)) {
215                 this.realmPrincipals = new HashMap<String,Map<String,Object>>();
216                 return this.realmPrincipals.put(realmName, new HashMap<String,Object>(principals));
217             } else {
218                 return null;
219             }
220         } else {
221             Map<String,Object> existingPrincipals = this.realmPrincipals.remove(realmName);
222             if (!CollectionUtils.isEmpty(principals)) {
223                 this.realmPrincipals.put(realmName, new HashMap<String,Object>(principals));
224             }
225             return existingPrincipals;
226         }
227     }
228 
229     public Object setRealmPrincipal(String realmName, String principalName, Object principal) {
230         if (realmName == null) {
231             throw new NullPointerException("realmName argument cannot be null.");
232         }
233         if (principalName == null) {
234             throw new NullPointerException(("principalName argument cannot be null."));
235         }
236         if (principal == null) {
237             return removeRealmPrincipal(realmName, principalName);
238         }
239         if (this.realmPrincipals == null) {
240             this.realmPrincipals = new HashMap<String,Map<String,Object>>();
241         }
242         Map<String,Object> principals = this.realmPrincipals.get(realmName);
243         if (principals == null) {
244             principals = new HashMap<String,Object>();
245             this.realmPrincipals.put(realmName, principals);
246         }
247         return principals.put(principalName, principal);
248     }
249 
250     public Object getRealmPrincipal(String realmName, String principalName) {
251         if (realmName == null) {
252             throw new NullPointerException("realmName argument cannot be null.");
253         }
254         if (principalName == null) {
255             throw new NullPointerException(("principalName argument cannot be null."));
256         }
257         if (this.realmPrincipals == null) {
258             return null;
259         }
260         Map<String,Object> principals = this.realmPrincipals.get(realmName);
261         if (principals != null) {
262             return principals.get(principalName);
263         }
264         return null;
265     }
266 
267     public Object removeRealmPrincipal(String realmName, String principalName) {
268         if (realmName == null) {
269             throw new NullPointerException("realmName argument cannot be null.");
270         }
271         if (principalName == null) {
272             throw new NullPointerException(("principalName argument cannot be null."));
273         }
274         if (this.realmPrincipals == null) {
275             return null;
276         }
277         Map<String,Object> principals = this.realmPrincipals.get(realmName);
278         if (principals != null) {
279             return principals.remove(principalName);
280         }
281         return null;
282     }
283 }