1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.shiro.subject;
20
21 import org.apache.shiro.util.CollectionUtils;
22 import org.apache.shiro.lang.util.StringUtils;
23
24 import java.io.IOException;
25 import java.io.ObjectInputStream;
26 import java.io.ObjectOutputStream;
27 import java.util.ArrayList;
28 import java.util.Collection;
29 import java.util.Collections;
30 import java.util.Iterator;
31 import java.util.LinkedHashMap;
32 import java.util.LinkedHashSet;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Objects;
36 import java.util.Set;
37
38
39
40
41
42
43
44 @SuppressWarnings({"unchecked"})
45 public class SimplePrincipalCollection implements MutablePrincipalCollection {
46
47
48
49
50
51
52 private static final long serialVersionUID = -6305224034025797558L;
53
54
55 private Map<String, Set> realmPrincipals;
56
57
58 private transient String cachedToString;
59
60 public SimplePrincipalCollection() {
61 }
62
63 public SimplePrincipalCollection(Object principal, String realmName) {
64 if (principal instanceof Collection) {
65 addAll((Collection) principal, realmName);
66 } else {
67 add(principal, realmName);
68 }
69 }
70
71 public SimplePrincipalCollection(Collection principals, String realmName) {
72 addAll(principals, realmName);
73 }
74
75 public SimplePrincipalCollection(PrincipalCollection principals) {
76 addAll(principals);
77 }
78
79 protected Collection getPrincipalsLazy(String realmName) {
80 if (realmPrincipals == null) {
81 realmPrincipals = new LinkedHashMap<String, Set>();
82 }
83 Set principals = realmPrincipals.get(realmName);
84 if (principals == null) {
85 principals = new LinkedHashSet();
86 realmPrincipals.put(realmName, principals);
87 }
88 return principals;
89 }
90
91
92
93
94
95
96
97
98
99
100 public Object getPrimaryPrincipal() {
101 if (isEmpty()) {
102 return null;
103 }
104 return iterator().next();
105 }
106
107 public void add(Object principal, String realmName) {
108 if (realmName == null) {
109 throw new NullPointerException("realmName argument cannot be null.");
110 }
111 if (principal == null) {
112 throw new NullPointerException("principal argument cannot be null.");
113 }
114 this.cachedToString = null;
115 getPrincipalsLazy(realmName).add(principal);
116 }
117
118 public void addAll(Collection principals, String realmName) {
119 if (realmName == null) {
120 throw new NullPointerException("realmName argument cannot be null.");
121 }
122 if (principals == null) {
123 throw new NullPointerException("principals argument cannot be null.");
124 }
125 if (principals.isEmpty()) {
126 throw new IllegalArgumentException("principals argument cannot be an empty collection.");
127 }
128 this.cachedToString = null;
129 getPrincipalsLazy(realmName).addAll(principals);
130 }
131
132 public void addAll(PrincipalCollection principals) {
133 if (principals.getRealmNames() != null) {
134 for (String realmName : principals.getRealmNames()) {
135 for (Object principal : principals.fromRealm(realmName)) {
136 add(principal, realmName);
137 }
138 }
139 }
140 }
141
142 public <T> T oneByType(Class<T> type) {
143 if (realmPrincipals == null || realmPrincipals.isEmpty()) {
144 return null;
145 }
146 Collection<Set> values = realmPrincipals.values();
147 for (Set set : values) {
148 for (Object o : set) {
149 if (type.isAssignableFrom(o.getClass())) {
150 return (T) o;
151 }
152 }
153 }
154 return null;
155 }
156
157 public <T> Collection<T> byType(Class<T> type) {
158 if (realmPrincipals == null || realmPrincipals.isEmpty()) {
159 return Collections.EMPTY_SET;
160 }
161 Set<T> typed = new LinkedHashSet<T>();
162 Collection<Set> values = realmPrincipals.values();
163 for (Set set : values) {
164 for (Object o : set) {
165 if (type.isAssignableFrom(o.getClass())) {
166 typed.add((T) o);
167 }
168 }
169 }
170 if (typed.isEmpty()) {
171 return Collections.EMPTY_SET;
172 }
173 return Collections.unmodifiableSet(typed);
174 }
175
176 public List asList() {
177 Set all = asSet();
178 if (all.isEmpty()) {
179 return Collections.EMPTY_LIST;
180 }
181 return Collections.unmodifiableList(new ArrayList(all));
182 }
183
184 public Set asSet() {
185 if (realmPrincipals == null || realmPrincipals.isEmpty()) {
186 return Collections.EMPTY_SET;
187 }
188 Set aggregated = new LinkedHashSet();
189 Collection<Set> values = realmPrincipals.values();
190 for (Set set : values) {
191 aggregated.addAll(set);
192 }
193 if (aggregated.isEmpty()) {
194 return Collections.EMPTY_SET;
195 }
196 return Collections.unmodifiableSet(aggregated);
197 }
198
199 public Collection fromRealm(String realmName) {
200 if (realmPrincipals == null || realmPrincipals.isEmpty()) {
201 return Collections.EMPTY_SET;
202 }
203 Set principals = realmPrincipals.get(realmName);
204 if (principals == null || principals.isEmpty()) {
205 principals = Collections.EMPTY_SET;
206 }
207 return Collections.unmodifiableSet(principals);
208 }
209
210 public Set<String> getRealmNames() {
211 if (realmPrincipals == null) {
212 return null;
213 } else {
214 return realmPrincipals.keySet();
215 }
216 }
217
218 public boolean isEmpty() {
219 return realmPrincipals == null || realmPrincipals.isEmpty();
220 }
221
222 public void clear() {
223 this.cachedToString = null;
224 if (realmPrincipals != null) {
225 realmPrincipals.clear();
226 realmPrincipals = null;
227 }
228 }
229
230 public Iterator iterator() {
231 return asSet().iterator();
232 }
233
234 public boolean equals(Object o) {
235 if (o == this) {
236 return true;
237 }
238 if (o instanceof SimplePrincipalCollection) {
239 SimplePrincipalCollection other = (SimplePrincipalCollection) o;
240 return Objects.equals(this.realmPrincipals, other.realmPrincipals);
241 }
242 return false;
243 }
244
245 public int hashCode() {
246 if (this.realmPrincipals != null && !realmPrincipals.isEmpty()) {
247 return realmPrincipals.hashCode();
248 }
249 return super.hashCode();
250 }
251
252
253
254
255
256
257
258 public String toString() {
259 if (this.cachedToString == null) {
260 Set<Object> principals = asSet();
261 if (!CollectionUtils.isEmpty(principals)) {
262 this.cachedToString = StringUtils.toString(principals.toArray());
263 } else {
264 this.cachedToString = "empty";
265 }
266 }
267 return this.cachedToString;
268 }
269
270
271
272
273
274
275
276
277
278
279
280
281 private void writeObject(ObjectOutputStream out) throws IOException {
282 out.defaultWriteObject();
283 boolean principalsExist = !CollectionUtils.isEmpty(realmPrincipals);
284 out.writeBoolean(principalsExist);
285 if (principalsExist) {
286 out.writeObject(realmPrincipals);
287 }
288 }
289
290
291
292
293
294
295
296
297
298
299
300
301
302 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
303 in.defaultReadObject();
304 boolean principalsExist = in.readBoolean();
305 if (principalsExist) {
306 this.realmPrincipals = (Map<String, Set>) in.readObject();
307 }
308 }
309 }