code: /**
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements. See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership. The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License. You may obtain a copy of the License at
   *
   * http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing,
   * software distributed under the License is distributed on an
   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   * KIND, either express or implied. See the License for the
   * specific language governing permissions and limitations
   * under the License.
   */
  
  package org.apache.cxf.ws.security.trust;
  
  import java.util.LinkedList;
  import java.util.List;
  import java.util.logging.Level;
  import java.util.logging.Logger;
  
  import org.w3c.dom.Element;
  
  import org.apache.cxf.Bus;
  import org.apache.cxf.common.logging.LogUtils;
  import org.apache.cxf.common.util.StringUtils;
  import org.apache.cxf.helpers.DOMUtils;
  import org.apache.cxf.interceptor.Fault;
  import org.apache.cxf.ws.security.tokenstore.SecurityToken;
  
  /**
   * A extension of AbstractSTSClient to communicate with an STS and return a SecurityToken
   * to the client.
   */
  public class STSClient extends AbstractSTSClient {
      private static final Logger LOG = LogUtils.getL7dLogger(STSClient.class);
      
      public STSClient(Bus b) {
          super(b);
      }
  
      public SecurityToken requestSecurityToken() throws Exception {
          return requestSecurityToken(null);
      }
  
      public SecurityToken requestSecurityToken(String appliesTo) throws Exception {
          return requestSecurityToken(appliesTo, null);
      }
      
      public SecurityToken requestSecurityToken(String appliesTo, String binaryExchange) throws Exception {
          return requestSecurityToken(appliesTo, null, "/Issue", binaryExchange);
      }
      
      public SecurityToken requestSecurityToken(
          String appliesTo, String action, String requestType, String binaryExchange
      ) throws Exception {
          STSResponse response = issue(appliesTo, action, requestType, binaryExchange);
  
          SecurityToken token = 
              createSecurityToken(getDocumentElement(response.getResponse()), response.getEntropy());
          
          if (response.getCert() != null) {
              token.setX509Certificate(response.getCert(), response.getCrypto());
          }
          if (token.getTokenType() == null) {
              String tokenTypeFromTemplate = getTokenTypeFromTemplate();
              if (tokenTypeFromTemplate != null) {
                  token.setTokenType(tokenTypeFromTemplate);
              } else if (tokenType != null) {
                  token.setTokenType(tokenType);
              }
          }
          return token;
      }
      
      public SecurityToken renewSecurityToken(SecurityToken tok) throws Exception {
          STSResponse response = renew(tok);
  
          SecurityToken token = createSecurityToken(getDocumentElement(response.getResponse()), null);
          if (token.getTokenType() == null) {
              String tokenTypeFromTemplate = getTokenTypeFromTemplate();
              if (tokenTypeFromTemplate != null) {
                  token.setTokenType(tokenTypeFromTemplate);
              } else if (tokenType != null) {
                  token.setTokenType(tokenType);
              }
          }
          return token;
      }
  
      public List<SecurityToken> validateSecurityToken(SecurityToken tok) throws Exception {
          String validateTokenType = tokenType;
          if (validateTokenType == null) {
              validateTokenType = namespace + "/RSTR/Status";
          }
          return validateSecurityToken(tok, validateTokenType);
      }
      
      protected List<SecurityToken> validateSecurityToken(SecurityToken tok, String tokentype) 
          throws Exception {
          STSResponse response = validate(tok, tokentype);
          
          Element el = getDocumentElement(response.getResponse());
          if ("RequestSecurityTokenResponseCollection".equals(el.getLocalName())) {
              el = DOMUtils.getFirstElement(el);
          }
          if (!"RequestSecurityTokenResponse".equals(el.getLocalName())) {
              throw new Fault("Unexpected element " + el.getLocalName(), LOG);
          }
          el = DOMUtils.getFirstElement(el);
          String reason = null;
          boolean valid = false;
          List<SecurityToken> tokens = new LinkedList<SecurityToken>();
          while (el != null) {
              if ("Status".equals(el.getLocalName())) {
                  Element e2 = DOMUtils.getFirstChildWithName(el, el.getNamespaceURI(), "Code");
                  String s = DOMUtils.getContent(e2);
                  valid = s.endsWith("/status/valid");
                  
                  e2 = DOMUtils.getFirstChildWithName(el, el.getNamespaceURI(), "Reason");
                  if (e2 != null) {
                      reason = DOMUtils.getContent(e2);
                  }
              } else if ("RequestedSecurityToken".equals(el.getLocalName())) {
                  Element requestedSecurityTokenElement = DOMUtils.getFirstElement(el);
                  String id = findID(null, null, requestedSecurityTokenElement);
                  if (StringUtils.isEmpty(id)) {
                      throw new TrustException("NO_ID", LOG);
                  }
                  SecurityToken requestedSecurityToken = new SecurityToken(id);
                  requestedSecurityToken.setToken(requestedSecurityTokenElement);
                  tokens.add(requestedSecurityToken);
              }
              el = DOMUtils.getNextElement(el);
          }
          if (!valid) {
              throw new TrustException(LOG, "VALIDATION_FAILED", reason);
          }
          if (tokens.isEmpty()) {
              tokens.add(tok);
          }
          return tokens;
      }
  
      public boolean cancelSecurityToken(SecurityToken token) throws Exception {
          try {
              cancel(token);
              return true;
          } catch (Exception ex) {
              LOG.log(Level.WARNING, "Problem cancelling token", ex);
              return false;
          }
      }
      
      private String getTokenTypeFromTemplate() {
          if (template != null && DOMUtils.getFirstElement(template) != null) {
              Element tl = DOMUtils.getFirstElement(template);
              while (tl != null) {
                  if ("TokenType".equals(tl.getLocalName())) {
                      return DOMUtils.getContent(tl);
                  }
                  tl = DOMUtils.getNextElement(tl);
              }
          }
          return null;
      }
      
  }
  