/**
  * Creates a SAML Assertion that can be used as a bearer token when invoking REST services. The
  * REST service must be configured to accept SAML Assertion bearer tokens.
  *
  * <p>In JBoss this means protecting the REST services with {@link SAMLBearerTokenLoginModule}. In
  * Tomcat7 this means protecting the REST services with {@link SAMLBearerTokenAuthenticator}.
  *
  * @param issuerName the issuer name (typically the context of the calling web app)
  * @param forService the web context of the REST service being invoked
  * @param timeValidInMillis how long the saml assertion should be valid for (in milliseconds)
  */
 public static String createSAMLAssertion(
     String issuerName, String forService, int timeValidInMillis) {
   SAMLAssertionFactory factory = getSAMLAssertionFactory();
   if (factory == null) {
     throw new RuntimeException(
         "Failed to create SAML Assertion:  Unsupported/undetected platform."); //$NON-NLS-1$
   } else {
     return factory.createSAMLAssertion(issuerName, forService, timeValidInMillis);
   }
 }
  /** @return the SAML assertion factory for the current runtime platform */
  private static SAMLAssertionFactory getSAMLAssertionFactory() {
    if (standardFactory.accept()) {
      return standardFactory;
    }

    if (cachedFactory != null) {
      return cachedFactory;
    }

    Set<SAMLAssertionFactory> factories = null;

    // Note: use our classloader when loading the services because the application-specific
    // overlord-commons-auth-* implementations will likely be packaged up with the generic
    // overlord-commons-auth (this) module.  The exception being OSGi, which
    // doesn't use ServiceLoader anyway.
    //
    // For example, when running in JBoss EAP 6.x, all of the overlord-commons-auth* JARs
    // are bundled up into a single JBoss Module.  In order for the ServiceLoader to work
    // properly, the context classloader would need to be set to the module's CL (so that
    // the service files are visible).
    ClassLoader oldCL = Thread.currentThread().getContextClassLoader();
    Thread.currentThread().setContextClassLoader(SAMLAssertionUtil.class.getClassLoader());
    try {
      factories = ServiceRegistryUtil.getServices(SAMLAssertionFactory.class);
    } finally {
      Thread.currentThread().setContextClassLoader(oldCL);
    }

    // Now that the factories are loaded, go ahead and try to use one of them.
    for (SAMLAssertionFactory factory : factories) {
      if (factory.accept()) {
        cachedFactory = factory;
        return factory;
      }
    }
    return null;
  }