1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package no.feide.moria.authorization;
21
22 import no.feide.moria.log.MessageLogger;
23 import org.jdom.Document;
24 import org.jdom.Element;
25 import org.jdom.JDOMException;
26 import org.jdom.input.SAXBuilder;
27
28 import java.io.File;
29 import java.io.IOException;
30 import java.util.HashMap;
31 import java.util.HashSet;
32 import java.util.Iterator;
33 import java.util.List;
34 import java.util.Properties;
35
36 /***
37 * The AuthorizationManager class is used to parse and store authorization data.
38 * The authorization data source is XML which is passed as a properties object
39 * through the setConfig method. The config data must contain information about
40 * every web service allowed to access Moria, and which attributes, operations
41 * and subsystems the service can access. <br>
42 * <br>
43 * When a new set of data arrives, the authorization manager parses it and
44 * replaces the old dataset if the parsing was successful. The authorization
45 * manager can then be used to answer authorization questions, most likely from
46 * the Moria controller. <br>
47 * <br>
48 * When the controller receives a request, it asks the authorization manager if
49 * the web service is authorized to perform the request. Every request includes
50 * the service principal.
51 * @author Lars Preben S. Arnesen <lars.preben.arnesen@conduct.no>
52 * @version $Revision: 1.35 $
53 */
54 public final class AuthorizationManager {
55
56 /***
57 * For logging of error messages that cannot be sent to the calling layer.
58 */
59 private final MessageLogger messageLogger = new MessageLogger(AuthorizationManager.class);
60
61 /***
62 * List of client authorization objects. Must be synchronized.
63 */
64 private HashMap authzClients = new HashMap();
65
66 /***
67 * List of attributes that is allowed to be cached.
68 */
69 private HashSet cachableAttributes = new HashSet();
70
71 /***
72 * True if the authorization manager is ready to be used.
73 */
74 private boolean activated = false;
75
76
77 /***
78 * Parses an XML element and creates an AuthorizationAttribute object in
79 * return. Throws an IllegalConfigException if there is something wrong with
80 * the element or its attributes.
81 * @param element
82 * The XML element to parse.
83 * @return AuthorizationAttribute with same attributes as the supplied
84 * <code>element</code>.
85 * @throws IllegalConfigException
86 * If the element's sso attribute is not <code>true</code> or
87 * <code>false</code>.
88 * @throws IllegalArgumentException
89 * If the <code>AuthorizationAttribute</code> constructor
90 * throws an exception.
91 */
92 static AuthorizationAttribute parseAttributeElem(final Element element)
93 throws IllegalConfigException {
94
95 String name = null;
96 String secLevel = null;
97 final String allowSSOStr;
98
99 if (element.getAttribute("name") != null) {
100 name = element.getAttribute("name").getValue();
101 }
102
103 if (element.getAttribute("sso") == null) {
104 throw new IllegalConfigException("allowSSO has to be set.");
105 } else {
106 allowSSOStr = element.getAttribute("sso").getValue();
107 if (!(allowSSOStr.equals("true") || allowSSOStr.equals("false"))) { throw new IllegalConfigException("allowSSO has to be 'true' or 'false'"); }
108 }
109
110 if (element.getAttribute("secLevel") != null) {
111 secLevel = element.getAttribute("secLevel").getValue();
112 }
113
114 try {
115 return new AuthorizationAttribute(name, new Boolean(allowSSOStr).booleanValue(), new Integer(secLevel).intValue());
116 } catch (IllegalArgumentException e) {
117 throw new IllegalConfigException("Illegal attributes: " + e.getMessage());
118 }
119 }
120
121
122 /***
123 * Parses the content of an Attributes element. The element can contain 0 or
124 * more Attribute elements which will be transformed into
125 * AuthorizationAttributes and returned in a HashMap with attribute name as
126 * key.
127 * @param element
128 * The DOM element that contains <code>Attribute</code> child
129 * elements.
130 * @return HashMap with AuthorizationAttributes as value and attribute name
131 * as key.
132 * @throws IllegalConfigException
133 * If <code>element</code> is not of type
134 * <code>Attributes</code>.
135 * @throws IllegalArgumentException
136 * If <code>element</code> is <code>null</code>.
137 */
138 static HashMap parseAttributesElem(final Element element)
139 throws IllegalConfigException {
140
141 final HashMap attributes = new HashMap();
142
143
144 if (element == null) { throw new IllegalArgumentException("Element cannot be null."); }
145
146 if (!element.getName().equalsIgnoreCase("attributes")) { throw new IllegalConfigException("Element isn't of type 'Attributes'"); }
147
148
149 final Iterator it = (element.getChildren()).iterator();
150 while (it.hasNext()) {
151 final AuthorizationAttribute attribute = parseAttributeElem((Element) it.next());
152 attributes.put(attribute.getName(), attribute);
153 }
154
155 return attributes;
156 }
157
158
159 /***
160 * Parses 'operation' and 'organization' elements and returns the name
161 * attribute.
162 * @param element
163 * The operation element.
164 * @return String containing the name attribute of the element.
165 * @throws IllegalConfigException
166 * If the element is not of type <code>Operation</code>,
167 * <code>Subsystem</code> or <code>Organization</code> OR
168 * element's <code>name</code> attribute is not set.
169 * @throws IllegalArgumentException
170 * If <code>element</code> is <code>null</code> or an empty
171 * string.
172 */
173 static String parseChildElem(final Element element)
174 throws IllegalConfigException {
175
176 if (element == null) { throw new IllegalArgumentException("Element cannot be null"); }
177
178 if (!element.getName().equalsIgnoreCase("Operation") && !element.getName().equalsIgnoreCase("Subsystem") && !element.getName().equalsIgnoreCase("Organization")) { throw new IllegalConfigException("Element must be of type 'Operation', 'Subsystem' or 'Organization'"); }
179
180 if (element.getAttribute("name") == null) { throw new IllegalConfigException("Element's name attribute must be set."); }
181
182 if (element.getAttributeValue("name").equalsIgnoreCase("")) { throw new IllegalConfigException("Element's name attribute cannot be an empty string."); }
183
184 return element.getAttributeValue("name");
185 }
186
187
188 /***
189 * Parses the content of an Attributes element. The element can contain 0 or
190 * more Attribute elements which will be transformed into
191 * AuthorizationAttributes and returned in a HashMap with attribute name as
192 * key.
193 * @param element
194 * The DOM element that contains Attribute child elements.
195 * @return HashMap with AuthorizationAttributes as value and attribute name
196 * as key.
197 * @throws IllegalConfigException
198 * If element is not of type <code>Operations</code>,
199 * <code>Affiliation</code>, <code>Subsystems</code> or
200 * <code>OrgsAllowed</code>.
201 * @throws IllegalArgumentException
202 * If <code>element</code> is <code>null</code>.
203 */
204 static HashSet parseListElem(final Element element)
205 throws IllegalConfigException {
206
207 final HashSet operations = new HashSet();
208
209
210 if (element == null) { throw new IllegalArgumentException("Element cannot be null."); }
211
212 if (!element.getName().equalsIgnoreCase("Operations") && !element.getName().equalsIgnoreCase("Subsystems") && !element.getName().equalsIgnoreCase("Affiliation") && !element.getName().equalsIgnoreCase("OrgsAllowed")) { throw new IllegalConfigException("Element isn't of type 'Operations', 'Subsystems', 'Affiliation' or 'OrgsAllowed'"); }
213
214
215 final Iterator it = (element.getChildren()).iterator();
216 while (it.hasNext()) {
217 final String operation = parseChildElem((Element) it.next());
218 operations.add(operation);
219 }
220
221 return operations;
222 }
223
224
225 /***
226 * Creates an AuthorizationClient object based on the supplied XML element.
227 * @param element
228 * The XML element representing the client service.
229 * @return A new object representing the client service.
230 * @throws IllegalConfigException
231 * If the <code>name</code> attribute is not set for the given
232 * element, or if any of the following tags are missing:
233 * <ul>
234 * <code>
235 * <li>DisplayName
236 * <li>URL
237 * <li>Language
238 * <li>Home
239 * <li>Attributes
240 * <li>Operations
241 * <li>Affiliation
242 * <li>OrgsAllowed
243 * </code>
244 * </ul>
245 * @throws IllegalArgumentException
246 * If <code>element</code> is <code>null</code>.
247 */
248 static AuthorizationClient parseClientElem(final Element element)
249 throws IllegalConfigException {
250
251
252 if (element == null)
253 throw new IllegalArgumentException("Client element cannot be null");
254
255
256 final String name;
257 final String displayName;
258 final String url;
259 final String language;
260 final String home;
261 final HashSet oper;
262 final HashSet affil;
263 final HashSet orgsAllowed;
264 HashSet subsys = null;
265 final HashMap attrs;
266
267
268 name = element.getAttributeValue("name");
269 if (name == null || name.equals(""))
270 throw new IllegalConfigException("Name attribute must be a non empty string.");
271
272
273 displayName = getChildContent(element, "DisplayName");
274 url = getChildContent(element, "URL");
275 language = getChildContent(element, "Language");
276 home = getChildContent(element, "Home");
277
278
279 Element child = element.getChild("Attributes");
280 if (child == null)
281 throw new IllegalConfigException("Attributes tag (Attributes) not found for client '" + name + "'");
282 attrs = parseAttributesElem(child);
283
284
285 child = element.getChild("Operations");
286 if (child == null)
287 throw new IllegalConfigException("Operations tag (Operations) not found for client '" + name + "'");
288 oper = parseListElem(child);
289
290
291 child = element.getChild("Affiliation");
292 if (child == null)
293 throw new IllegalConfigException("Affiliations tag (Affiliation) not found for client '" + name + "'");
294 affil = parseListElem(child);
295
296
297 child = element.getChild("OrgsAllowed");
298 if (child == null)
299 throw new IllegalConfigException("Organizations allowed tag (OrgsAllowed) not found for client '" + name + "'");
300 orgsAllowed = parseListElem(child);
301
302
303 child = element.getChild("Subsystems");
304 if (child != null)
305 subsys = parseListElem(child);
306
307 return new AuthorizationClient(name, displayName, url, language, home, affil, orgsAllowed, oper, subsys, attrs);
308 }
309
310
311 /***
312 * Parses a configuration root element with client elements.
313 * @param element
314 * The root element.
315 * @return A HashMap containing AuthorizationClient objects.
316 * @throws IllegalConfigException
317 * If the element is not of type
318 * <code>ClientAuthorizationConfig</code>.
319 * @throws IllegalArgumentException
320 * If <code>element</code> is <code>null</code>.
321 * @see AuthorizationClient
322 */
323 static HashMap parseRootElem(final Element element)
324 throws IllegalConfigException {
325
326 final HashMap clients = new HashMap();
327
328 if (element == null) { throw new IllegalArgumentException("Element cannot be null"); }
329
330 if (!element.getName().equalsIgnoreCase("ClientAuthorizationConfig")) { throw new IllegalConfigException("Wrong type of element: " + element.getName()); }
331
332 final List children = element.getChildren("Client");
333 final Iterator it = children.iterator();
334 while (it.hasNext()) {
335 final AuthorizationClient client = parseClientElem((Element) it.next());
336 clients.put(client.getName(), client);
337 }
338
339 return clients;
340 }
341
342
343 /***
344 * Retrieves the content of an XML element.
345 * @param element
346 * Parent element.
347 * @param childName
348 * Name of the child node.
349 * @return The content of the child element.
350 * @throws IllegalConfigException
351 * If the content of the child element is null.
352 */
353 private static String getChildContent(final Element element,
354 final String childName)
355 throws IllegalConfigException {
356
357 final String value = element.getChildText(childName);
358 if (value == null) {
359 throw new IllegalConfigException(childName + " tag not found");
360 } else {
361 return value;
362 }
363 }
364
365
366 /***
367 * Returns a client object for a given identifier.
368 * @param servicePrincipal
369 * The client object identifier.
370 * @return The client object for the identifier.
371 * @throws NoConfigException
372 * If the authorization manager is not activated.
373 * @throws IllegalArgumentException
374 * If <code>servicePrincipal</code> is <code>null</code> or
375 * an empty string.
376 */
377 private AuthorizationClient getAuthzClient(final String servicePrincipal) {
378
379
380 if (!activated) { throw new NoConfigException(); }
381
382
383 if (servicePrincipal == null || servicePrincipal.equals("")) { throw new IllegalArgumentException("servicePrincipal must be a non-empty string."); }
384
385 return (AuthorizationClient) authzClients.get(servicePrincipal);
386 }
387
388
389 /***
390 * Validates a request for access to attributes for a given client/service.
391 * @param servicePrincipal
392 * The identifier of the client.
393 * @param requestedAttributes
394 * The list of requested attributes.
395 * @return true if the service is allowed access, false if not or the client
396 * does not exist.
397 * @throws UnknownServicePrincipalException
398 * If the service principal does not exist.
399 */
400 public boolean allowAccessTo(final String servicePrincipal,
401 final String[] requestedAttributes)
402 throws UnknownServicePrincipalException {
403
404 final AuthorizationClient authzClient = getAuthzClient(servicePrincipal);
405
406 if (authzClient == null) { throw new UnknownServicePrincipalException("Service principal does not exist: '" + servicePrincipal + "'"); }
407
408 return authzClient.allowAccessTo(requestedAttributes);
409 }
410
411
412 /***
413 * Validates a request for access to SSO for a given client/service.
414 * @param servicePrincipal
415 * The identifier of the client.
416 * @param requestedAttributes
417 * The list of requested attributes.
418 * @return true if the service is allowed access, false if not or the client
419 * does not exist.
420 * @throws UnknownServicePrincipalException
421 * If the service principal does not exist.
422 */
423 public boolean allowSSOForAttributes(final String servicePrincipal,
424 final String[] requestedAttributes)
425 throws UnknownServicePrincipalException {
426
427 final AuthorizationClient authzClient = getAuthzClient(servicePrincipal);
428
429 if (authzClient == null) { throw new UnknownServicePrincipalException("Service principal does not exist: '" + servicePrincipal + "'"); }
430
431 return authzClient.allowSSOForAttributes(requestedAttributes);
432 }
433
434
435 /***
436 * Validates a request for access to operations for a given client/service.
437 * @param servicePrincipal
438 * The identifier of the client.
439 * @param requestedOperations
440 * The list of requested operations.
441 * @return true if the service is allowed access, false if not or the client
442 * does not exist.
443 * @throws UnknownServicePrincipalException
444 * If the servicePrincipal does not exist.
445 */
446 public boolean allowOperations(final String servicePrincipal,
447 final String[] requestedOperations)
448 throws UnknownServicePrincipalException {
449
450 final AuthorizationClient authzClient = getAuthzClient(servicePrincipal);
451
452 if (authzClient == null) { throw new UnknownServicePrincipalException("Service principal does not exist: '" + servicePrincipal + "'"); }
453
454 return authzClient.allowOperations(requestedOperations);
455 }
456
457
458 /***
459 * Checks if the organization is allowed to use the service.
460 * @param servicePrincipal
461 * The identifier of the client.
462 * @param userorg
463 * The user's organization.
464 * @return true if the organization is allowed to use the service, false if
465 * the client does not exists, or if the organization is not allowed
466 * to use the service.
467 * @throws UnknownServicePrincipalException
468 * If the servicePrincipal does not exist.
469 */
470 public boolean allowUserorg(final String servicePrincipal,
471 final String userorg)
472 throws UnknownServicePrincipalException {
473
474 final AuthorizationClient authzClient = getAuthzClient(servicePrincipal);
475
476 if (authzClient == null) { throw new UnknownServicePrincipalException("Service principal does not exist: '" + servicePrincipal + "'"); }
477
478 return authzClient.allowUserorg(userorg);
479 }
480
481
482 /***
483 * Swaps the old client database with the supplied HashMap.
484 * @param newClients
485 * The new client database.
486 * @throws IllegalArgumentException
487 * If <code>newClients</code> is <code>null</code>.
488 */
489 synchronized void setAuthzClients(final HashMap newClients) {
490
491 if (newClients == null) { throw new IllegalArgumentException("newClients to be set cannot be null"); }
492
493
494 final HashSet newCachableAttributes = new HashSet();
495 final Iterator clientIt = newClients.keySet().iterator();
496 while (clientIt.hasNext()) {
497 final AuthorizationClient authzClient = (AuthorizationClient) newClients.get(clientIt.next());
498
499 final HashMap attributes = authzClient.getAttributes();
500 final Iterator attrIt = attributes.keySet().iterator();
501 while (attrIt.hasNext()) {
502 final AuthorizationAttribute attr = (AuthorizationAttribute) attributes.get(attrIt.next());
503 if (attr.getAllowSSO()) {
504 newCachableAttributes.add(attr.getName());
505 }
506 }
507 }
508
509
510 synchronized (authzClients) {
511 authzClients = newClients;
512 cachableAttributes = newCachableAttributes;
513 activated = true;
514 }
515 }
516
517
518 /***
519 * Sets the configuration data for this manager.
520 * @param properties
521 * The properties containing the authorization database.
522 * @throws IllegalArgumentException
523 * If <code>properties</code> is <code>null</code>.
524 */
525 public void setConfig(final Properties properties) {
526
527
528 if (properties == null)
529 throw new IllegalArgumentException("Properties cannot be null");
530 final String fileName = (String) properties.get("authorizationDatabase");
531 if (fileName == null || fileName.equals("")) {
532 messageLogger.logWarn("The 'authorizationDatabase' property is not set or an empty string");
533 return;
534 }
535 File database = new File(fileName);
536 if (!database.exists()) {
537 messageLogger.logWarn("Authorization database file '" + fileName + "' does not exist");
538 return;
539 }
540
541
542 final SAXBuilder builder = new SAXBuilder();
543 try {
544
545 final Document doc = builder.build(database);
546 final HashMap newClients = parseRootElem(doc.getRootElement());
547 setAuthzClients(newClients);
548
549 } catch (JDOMException e) {
550 messageLogger.logWarn("Error parsing authorization database file '" + fileName + " - using old database", e);
551 } catch (IOException e) {
552 messageLogger.logWarn("Error reading authorization database file '" + fileName + " - using old database", e);
553 } catch (IllegalConfigException e) {
554 messageLogger.logWarn("Error generating authorization database - using old database", e);
555 }
556
557 }
558
559
560 /***
561 * Returns the service properties for a given service.
562 * @param servicePrincipal
563 * The principal of the service.
564 * @return A hashmap with properties for a given service.
565 * @throws UnknownServicePrincipalException
566 * If the service principal does not exist.
567 * @throws IllegalArgumentException
568 * If <code>servicePrincipal</code> is <code>null</code> or
569 * an empty string.
570 * @see AuthorizationClient#getProperties()
571 */
572 public HashMap getServiceProperties(final String servicePrincipal)
573 throws UnknownServicePrincipalException {
574
575
576 if (servicePrincipal == null || servicePrincipal.equals("")) { throw new IllegalArgumentException("servicePrincipal must be a non-empty string"); }
577
578 final AuthorizationClient authzClient = getAuthzClient(servicePrincipal);
579 if (authzClient == null) { throw new UnknownServicePrincipalException("Service principal does not exist: '" + servicePrincipal + "'"); }
580
581 return authzClient.getProperties();
582 }
583
584
585 /***
586 * Returns the security level for a set of attributes for a given service.
587 * @param servicePrincipal
588 * The service principal of the requested service.
589 * @param requestedAttributes
590 * The requested attributes.
591 * @return Security level - an integer >= 0.
592 * @throws UnknownServicePrincipalException
593 * If the service principal does not exist.
594 * @throws UnknownAttributeException
595 * If one or more of the requested attributes does not exist.
596 * @throws IllegalArgumentException
597 * If <code>servicePrincipal</code> is <code>null</code> or
598 * an empty string, or if <code>requestedAttributes</code> is
599 * <code>null</code>.
600 * @see AuthorizationClient#getSecLevel(java.lang.String[])
601 */
602 public int getSecLevel(final String servicePrincipal,
603 final String[] requestedAttributes)
604 throws UnknownServicePrincipalException, UnknownAttributeException {
605
606
607 if (servicePrincipal == null || servicePrincipal.equals("")) { throw new IllegalArgumentException("servicePrincipal must be a non-empty string"); }
608 if (requestedAttributes == null) { throw new IllegalArgumentException("requestedAttributes cannot be null"); }
609
610 final AuthorizationClient authzClient = getAuthzClient(servicePrincipal);
611 if (authzClient == null) { throw new UnknownServicePrincipalException("Service principal does not exist: '" + servicePrincipal + "'"); }
612
613
614 if (requestedAttributes.length == 0) { return 0; }
615
616 return authzClient.getSecLevel(requestedAttributes);
617 }
618
619
620 /***
621 * Returns the configured attributes for a given service.
622 * @param servicePrincipal
623 * The principal of the requested service.
624 * @return A string array with the attribute names that is configured for
625 * the service.
626 * @throws UnknownServicePrincipalException
627 * If the servicePrincipal does not exist.
628 * @throws IllegalArgumentException
629 * If <code>servicePrincipal</code> is <code>null</code> or
630 * an empty string.
631 * @see AuthorizationClient#getAttributes()
632 */
633 public HashSet getAttributes(final String servicePrincipal)
634 throws UnknownServicePrincipalException {
635
636
637 if (servicePrincipal == null || servicePrincipal.equals("")) { throw new IllegalArgumentException("servicePrincipal must be a non-empty string"); }
638
639 final AuthorizationClient authzClient = getAuthzClient(servicePrincipal);
640 if (authzClient == null) { throw new UnknownServicePrincipalException("Service principal does not exist: '" + servicePrincipal + "'"); }
641
642 return new HashSet(authzClient.getAttributes().keySet());
643 }
644
645
646 /***
647 * Returns the organizations that can use this service.
648 * @param servicePrincipal
649 * The principal of the requested service.
650 * @return A string array with the names of the allowed organizations for
651 * the service.
652 * @throws UnknownServicePrincipalException
653 * If the servicePrincipal does not exist.
654 * @throws IllegalArgumentException
655 * If <code>servicePrincipal</code> is <code>null</code> or
656 * an empty string.
657 * @see AuthorizationClient#getOrgsAllowed()
658 */
659 public HashSet getOrgsAllowed(final String servicePrincipal)
660 throws UnknownServicePrincipalException {
661
662
663 if (servicePrincipal == null || servicePrincipal.equals("")) { throw new IllegalArgumentException("servicePrincipal must be a non-empty string"); }
664
665 final AuthorizationClient authzClient = getAuthzClient(servicePrincipal);
666 if (authzClient == null) { throw new UnknownServicePrincipalException("Service principal does not exist: '" + servicePrincipal + "'"); }
667
668 return authzClient.getOrgsAllowed();
669 }
670
671
672 /***
673 * Returns the configured subsystems for a given service.
674 * @param servicePrincipal
675 * The principal of the requested service,
676 * @return A string array with the subsystem names that is configured for
677 * the service.
678 * @throws UnknownServicePrincipalException
679 * If the servicePrincipal does not exist.
680 * @throws IllegalArgumentException
681 * If <code>servicePrincipal</code> is <code>null</code> or
682 * an empty string.
683 * @see AuthorizationClient#getSubsystems()
684 */
685 public HashSet getSubsystems(final String servicePrincipal)
686 throws UnknownServicePrincipalException {
687
688
689 if (servicePrincipal == null || servicePrincipal.equals("")) { throw new IllegalArgumentException("servicePrincipal must be a non-empty string"); }
690
691 final AuthorizationClient authzClient = getAuthzClient(servicePrincipal);
692 if (authzClient == null) { throw new UnknownServicePrincipalException("Service principal does not exist: '" + servicePrincipal + "'"); }
693
694 return authzClient.getSubsystems();
695 }
696
697
698 /***
699 * Returns the configured operations for a given service.
700 * @param servicePrincipal
701 * The principal of the requested service.
702 * @return A string array with the operation names that is configured for
703 * the service.
704 * @throws UnknownServicePrincipalException
705 * If the servicePrincipal does not exist.
706 * @throws IllegalArgumentException
707 * If <code>servicePrincipal</code> is <code>null</code> or
708 * an empty string.
709 * @see AuthorizationClient#getOperations()
710 */
711 public HashSet getOperations(final String servicePrincipal)
712 throws UnknownServicePrincipalException {
713
714
715 if (servicePrincipal == null || servicePrincipal.equals("")) { throw new IllegalArgumentException("servicePrincipal must be a non-empty string"); }
716
717 final AuthorizationClient authzClient = getAuthzClient(servicePrincipal);
718 if (authzClient == null)
719 throw new UnknownServicePrincipalException("Unknown service principal: '" + servicePrincipal + "'");
720
721 return authzClient.getOperations();
722 }
723
724
725 /***
726 * Returns the set of SSO attributes names (the attributes that can be
727 * cached).
728 * @return A set of attributes that can be cached.
729 */
730 public HashSet getCachableAttributes() {
731
732 return new HashSet(cachableAttributes);
733 }
734
735
736 /***
737 * Get the list of attribute names not allowed for use in an SSO context for
738 * a given service.
739 * @param servicePrincipal
740 * The service principal. Must be a non-empty string.
741 * @return An array of attribute names. May be an empty array, but never
742 * <code>null</code>.
743 * @throws UnknownServicePrincipalException
744 * If the <code>servicePrincipal</code> is unknown.
745 * @throws IllegalArgumentException
746 * If <code>servicePrincipal</code> is <code>null</code> or
747 * an empty string.
748 */
749 public String[] getNonSSOAttributeNames(final String servicePrincipal)
750 throws UnknownServicePrincipalException, IllegalArgumentException {
751
752
753 if (servicePrincipal == null || servicePrincipal.equals(""))
754 throw new IllegalArgumentException("Service principal must be a non-empty string");
755
756
757 final AuthorizationClient client = getAuthzClient(servicePrincipal);
758 if (client == null)
759 throw new UnknownServicePrincipalException("Unknown service principal: '" + servicePrincipal + "'");
760
761 return client.getNonSSOAttributeNames();
762 }
763 }