Jasig/cas — pull request #446 by mmoayyed (2014-06-20 20:07:47+00:00)
Title: CAS-1475: Refactoring of GoogleApps altUsername config

I started out with the original premise of this JIRA:

> The GoogleApps service currently declares a custom property to determine an optional and alternate username attribute to be sent back to Google. CAS 3.5.x adds the ability to configure username attributes per service, rendering the Google altUsername config unneeded.

https://issues.jasig.org/browse/CAS-1475

This pull request is the result of refactoring the usernameAttribute-per-service API that exists as of CAS 3.5. While I was working on the GoogleApps-related change, I realized that the determination of the uid per service is complected in CAS impl and is dependent on a number of other variables and settings in the registry that could easily be turned into logical abstractions, and used one at a time to simplify the configuration. This pull is the result of that effort.

Aside from making sure the GoogleApps integration design-wise is consistent with the service registry config, my other goal was to attempt to reduce CASImpl's complexity, by taking one-off if-conditions and turning them into logical abstractions, and more importantly extension points. The idea for extension points was also inspired by a few recent projects where there were strict and rather complicated requirements for calculating the username for a given service that involved multiple systems, etc. So in part, the refactoring opens up the possibilty of not having to fork CASImpl but just to extend a class to encapsulate the logic needed for uid of a service.

The following is included in this pull:

* There are three possible options for a username returned to a service:

1) default principal id
2) anonymous id
3) principal attribute

Inspired by PersonDirectory, in this pull each registered service includes a `RegisteredServiceUsernameAttributeProvider`, and there are 3 possible implementations for the above points.

###DefaultRegisteredServiceUsernameProvider
The default principal id, case (1), as the username...this is the default provider for each service.

###AnonymousRegisteredServiceUsernameAttributeProvider
Case (2)

###PrincipalAttributeRegisteredServiceUsernameProvider
Case (3)

To figure out the attribute, one would need to call from CASImpl:

```java
final String principalId = registeredService.getUsernameAttributeProvider().resolveUsername(principal);
```

Adopters of course would need to configure each service with the relevant provider. The default is used if none is configured.