[jboss-cvs] Picketlink SVN: r265 - federation/trunk/picketlink-fed-api/src/main/java/org/picketlink/identity/federation/api/wstrust.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Thu May 27 14:31:01 EDT 2010
Author: sguilhen at redhat.com
Date: 2010-05-27 14:31:00 -0400 (Thu, 27 May 2010)
New Revision: 265
Modified:
federation/trunk/picketlink-fed-api/src/main/java/org/picketlink/identity/federation/api/wstrust/WSTrustClient.java
Log:
PLFED-75: Failover support - WSTrustClient now has a constructor that accepts an array of endpoint URIs. If, when issuing/renewing/validating a token, a connection can't be established with one endpoint, the code attempts to invoke the next endpoint until the request reaches an active STS instance or all URIs have been tried.
Modified: federation/trunk/picketlink-fed-api/src/main/java/org/picketlink/identity/federation/api/wstrust/WSTrustClient.java
===================================================================
--- federation/trunk/picketlink-fed-api/src/main/java/org/picketlink/identity/federation/api/wstrust/WSTrustClient.java 2010-05-26 20:24:39 UTC (rev 264)
+++ federation/trunk/picketlink-fed-api/src/main/java/org/picketlink/identity/federation/api/wstrust/WSTrustClient.java 2010-05-27 18:31:00 UTC (rev 265)
@@ -37,105 +37,245 @@
*/
public class WSTrustClient
{
- /**
- * The STSClient that this class delegates to.
- */
- private STSClient stsClient;
-
- public static class SecurityInfo
- {
- private String username;
- private String passwd;
+ /**
+ * The array of STSClient instances that this class delegates to.
+ */
+ private STSClient[] clients;
- public SecurityInfo(String name, char[] pass)
- {
- username = name;
- passwd = new String(pass);
- }
+ public static class SecurityInfo
+ {
+ private String username;
- public SecurityInfo(String name, String pass)
- {
- username = name;
- passwd = pass;
- }
- }
+ private String passwd;
- public WSTrustClient(String serviceName, String port, String endpointURI, SecurityInfo secInfo) throws ParsingException
- {
- Builder builder = new STSClientConfig.Builder();
- builder.serviceName(serviceName).portName(port).endpointAddress(endpointURI).username(secInfo.username).password(secInfo.passwd);
- stsClient = STSClientFactory.getInstance().create(builder.build());
- }
+ public SecurityInfo(String name, char[] pass)
+ {
+ username = name;
+ passwd = new String(pass);
+ }
- /**
- * This method will send a RequestSecurityToken with a RequestType of issue
- * and the passed-in tokenType identifies the type of token to be issued by
- * the STS.
- *
- * @param tokenType - The type of token to be issued.
- * @return Element - The Security Token element. Will be of the tokenType specified.
- * @throws WSTrustException
- */
- public Element issueToken(String tokenType) throws WSTrustException
- {
- return stsClient.issueToken(tokenType);
- }
-
- /**
- * This method will send a RequestSecurityToken with a RequestType of issue
- * and the passed-in endpointURI identifies the ultimate recipient of the token.
- *
- * @param endpointURI - The ultimate recipient of the token. This will be set at the AppliesTo for
- * the RequestSecurityToken which is an optional element so it may be null.
- * @return Element - The Security Token element. Will be of the tokenType configured for the endpointURI.
- * @throws WSTrustException
- */
- public Element issueTokenForEndpoint(String endpointURI) throws WSTrustException
- {
- return stsClient.issueTokenForEndpoint(endpointURI);
- }
-
- /**
- * Issues a Security Token from the STS. This methods has the option of
- * specifying both or one of endpointURI/tokenType but at least one must
- * specified.
- *
- * @param endpointURI - The ultimate recipient of the token. This will be set at the AppliesTo for
- * the RequestSecurityToken which is an optional element so it may be null.
- * @param tokenType - The type of security token to be issued.
- * @return Element - The Security Token Element issued.
- * @throws IllegalArgumentException If neither endpointURI nor tokenType was specified.
- * @throws WSTrustException
- */
- public Element issueToken(String endpointURI, String tokenType) throws WSTrustException
- {
- return stsClient.issueToken(endpointURI, tokenType);
- }
-
- /**
- * This method will send a RequestSecurityToken with a RequestType of renew
- * and the passed-in tokenType identifies the type of token to be renewed by
- * the STS.
- *
- * @param tokenType - The type of token to be renewed.
- * @param token - The security token to be renewed.
- * @return Element - The Security Token element. Will be of the tokenType specified.
- */
- public Element renewToken(String tokenType, Element token) throws WSTrustException
- {
- return stsClient.renewToken(tokenType, token);
- }
+ public SecurityInfo(String name, String pass)
+ {
+ username = name;
+ passwd = pass;
+ }
+ }
- /**
- * This method will send a RequestSecurityToken with a RequestType of validated by
- * the STS.
- *
- * @param token - The security token to be validated.
- * @return true - If the security token was sucessfully valiated.
- */
- public boolean validateToken(Element token) throws WSTrustException
- {
- return stsClient.validateToken(token);
- }
+ public WSTrustClient(String serviceName, String port, String endpointURI, SecurityInfo secInfo)
+ throws ParsingException
+ {
+ this(serviceName, port, new String[]{endpointURI}, secInfo);
+ }
+ public WSTrustClient(String serviceName, String port, String[] endpointURIs, SecurityInfo secInfo)
+ throws ParsingException
+ {
+ // basic input validation.
+ if (serviceName == null || port == null || endpointURIs == null || secInfo == null)
+ throw new IllegalArgumentException(
+ "The service name, port, endpoint URIs and security info parameters cannot be null");
+ if (endpointURIs.length == 0)
+ throw new IllegalArgumentException("At least one endpoint URI must be informed");
+
+ // create an STSClient for each endpointURI.
+ this.clients = new STSClient[endpointURIs.length];
+ Builder builder = new STSClientConfig.Builder();
+ builder.serviceName(serviceName).portName(port).username(secInfo.username).password(secInfo.passwd);
+
+ int index = 0;
+ for (String endpointURI : endpointURIs)
+ {
+ builder.endpointAddress(endpointURI);
+ this.clients[index++] = STSClientFactory.getInstance().create(builder.build());
+ }
+
+ }
+
+ /**
+ * This method will send a RequestSecurityToken with a RequestType of issue
+ * and the passed-in tokenType identifies the type of token to be issued by
+ * the STS.
+ *
+ * @param tokenType - The type of token to be issued.
+ * @return Element - The Security Token element. Will be of the tokenType specified.
+ * @throws WSTrustException
+ */
+ public Element issueToken(String tokenType) throws WSTrustException
+ {
+ return this.issueInternal(null, tokenType, 0);
+ }
+
+ /**
+ * This method will send a RequestSecurityToken with a RequestType of issue
+ * and the passed-in endpointURI identifies the ultimate recipient of the token.
+ *
+ * @param endpointURI - The ultimate recipient of the token. This will be set at the AppliesTo for
+ * the RequestSecurityToken which is an optional element so it may be null.
+ * @return Element - The Security Token element. Will be of the tokenType configured for the endpointURI.
+ * @throws WSTrustException
+ */
+ public Element issueTokenForEndpoint(String endpointURI) throws WSTrustException
+ {
+ return this.issueInternal(endpointURI, null, 0);
+ }
+
+ /**
+ * Issues a Security Token from the STS. This methods has the option of
+ * specifying both or one of endpointURI/tokenType but at least one must
+ * specified.
+ *
+ * @param endpointURI - The ultimate recipient of the token. This will be set at the AppliesTo for
+ * the RequestSecurityToken which is an optional element so it may be null.
+ * @param tokenType - The type of security token to be issued.
+ * @return Element - The Security Token Element issued.
+ * @throws IllegalArgumentException If neither endpointURI nor tokenType was specified.
+ * @throws WSTrustException
+ */
+ public Element issueToken(String endpointURI, String tokenType) throws WSTrustException
+ {
+ return this.issueInternal(endpointURI, tokenType, 0);
+ }
+
+ /**
+ * This method will send a RequestSecurityToken with a RequestType of renew
+ * and the passed-in tokenType identifies the type of token to be renewed by
+ * the STS.
+ *
+ * @param tokenType - The type of token to be renewed.
+ * @param token - The security token to be renewed.
+ * @return Element - The Security Token element. Will be of the tokenType specified.
+ */
+ public Element renewToken(String tokenType, Element token) throws WSTrustException
+ {
+ return this.renewInternal(tokenType, token, 0);
+ }
+
+ /**
+ * This method will send a RequestSecurityToken with a RequestType of validated by
+ * the STS.
+ *
+ * @param token - The security token to be validated.
+ * @return true - If the security token was sucessfully valiated.
+ */
+ public boolean validateToken(Element token) throws WSTrustException
+ {
+ return this.validateInternal(token, 0);
+ }
+
+ /**
+ * <p>
+ * This method issues a token of the specified type for the specified service endpoint and has failover support when
+ * more than one endpoint URI has been provided in the constructor. If a {@code ConnectException} occurs when sending
+ * the WS-Trust request to one endpoint, the code makes a new attempt using the next URI until the request reaches an
+ * STS instance or all URIs have been tried.
+ * </p>
+ *
+ * @param serviceEndpointURI a {@code String} representing the endpoint URI of the service that will be the ultimate
+ * recipient of the security token.
+ * @param tokenType a {@code String} representing the type of token to be issued.
+ * @param clientIndex an {@code int} that indicates which of the {@code STSClient} instances should be used to perform
+ * the request.
+ * @return an {@code Element} representing the security token that has been issued.
+ * @throws WSTrustException if a WS-Trust exception is thrown by the STS.
+ */
+ private Element issueInternal(String serviceEndpointURI, String tokenType, int clientIndex) throws WSTrustException
+ {
+ STSClient client = this.clients[clientIndex];
+ try
+ {
+ return client.issueToken(serviceEndpointURI, tokenType);
+ }
+ catch (RuntimeException e)
+ {
+ // if this was a connection refused exception and we still have clients to try, call the next client.
+ if (this.isCausedByConnectException(e) && clientIndex < this.clients.length - 1)
+ {
+ return this.issueInternal(serviceEndpointURI, tokenType, ++clientIndex);
+ }
+ throw e;
+ }
+ }
+
+ /**
+ * <p>
+ * This method renews the specified token and has failover support when more than one endpoint URI has been provided
+ * in the constructor. If a {@code ConnectException} occurs when sending the WS-Trust request to one endpoint, the
+ * code makes a new attempt using the next URI until the request reaches an STS instance or all URIs have been tried.
+ * </p>
+ *
+ * @param tokenType the type of the token being renewed.
+ * @param token an {@code Element} representing the security token being renewed.
+ * @param clientIndex an {@code int} that indicates which of the {@code STSClient} instances should be used to perform
+ * the request.
+ * @return an {@code Element} representing the security token that has been renewed.
+ * @throws WSTrustException if a WS-Trust exception is thrown by the STS.
+ */
+ private Element renewInternal(String tokenType, Element token, int clientIndex) throws WSTrustException
+ {
+ STSClient client = this.clients[clientIndex];
+ try
+ {
+ return client.renewToken(tokenType, token);
+ }
+ catch (RuntimeException e)
+ {
+ // if this was a connection refused exception and we still have clients to try, call the next client.
+ if (this.isCausedByConnectException(e) && clientIndex < this.clients.length - 1)
+ {
+ return this.renewInternal(tokenType, token, ++clientIndex);
+ }
+ throw e;
+ }
+ }
+
+ /**
+ * <p>
+ * This method validates the specified token and has failover support when more than one endpoint URI has been provided
+ * in the constructor. If a {@code ConnectException} occurs when sending the WS-Trust request to one endpoint, the
+ * code makes a new attempt using the next URI until the request reaches an STS instance or all URIs have been tried.
+ * </p>
+ *
+ * @param token an {@code Element} representing the security token being validated.
+ * @param clientIndex an {@code int} that indicates which of the {@code STSClient} instances should be used to perform
+ * the request.
+ * @return {@code true} if the token was considered valid; {@code false} otherwise.
+ * @throws WSTrustException if a WS-Trust exception is thrown by the STS.
+ */
+ private boolean validateInternal(Element token, int clientIndex) throws WSTrustException
+ {
+ STSClient client = this.clients[clientIndex];
+ try
+ {
+ return client.validateToken(token);
+ }
+ catch (RuntimeException e)
+ {
+ // if this was a connection refused exception and we still have clients to try, call the next client.
+ if (this.isCausedByConnectException(e) && clientIndex < this.clients.length - 1)
+ {
+ return this.validateInternal(token, ++clientIndex);
+ }
+ throw e;
+ }
+ }
+
+ /**
+ * <p>
+ * Checks if the root of the specified {@code Throwable} is an instance of {@code java.net.ConnectException}.
+ * </p>
+ *
+ * @param throwable the {@code Throwable} that will be inspected.
+ * @return {@code true} if the root cause is a {@code java.net.ConnectException}; {@code false} otherwise.
+ */
+ private boolean isCausedByConnectException(Throwable throwable)
+ {
+ // iterate through the causes until we reach the root cause.
+ while (throwable.getCause() != null)
+ throwable = throwable.getCause();
+
+ // check if the root throwable is a ConnectException.
+ if (throwable instanceof java.net.ConnectException && throwable.getMessage().equals("Connection refused"))
+ return true;
+ return false;
+ }
}
\ No newline at end of file
More information about the jboss-cvs-commits
mailing list