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