package cat.aoc.pci.utils;

import java.io.IOException;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;

import org.apache.ws.security.WSPasswordCallback;

public class PWCallback implements CallbackHandler
{
  private static final byte[] key = {
  (byte) 0x31, (byte) 0xfd, (byte) 0xcb, (byte) 0xda, (byte) 0xfb,
  (byte) 0xcd, (byte) 0x6b, (byte) 0xa8, (byte) 0xe6, (byte) 0x19,
  (byte) 0xa7, (byte) 0xbf, (byte) 0x51, (byte) 0xf7, (byte) 0xc7,
  (byte) 0x3e, (byte) 0x80, (byte) 0xae, (byte) 0x98, (byte) 0x51,
  (byte) 0xc8, (byte) 0x51, (byte) 0x34, (byte) 0x04,
  };

  // ----------------------------------------------------------- CallbackHandler
  /*
   * (non-Javadoc)
   *
   * @see javax.security.auth.callback.CallbackHandler#handle(javax.security.auth.callback.Callback[])
   */
  public void handle(Callback[] callbacks) throws IOException,
      UnsupportedCallbackException
  {
    for (int i = 0; i < callbacks.length; i++)
    {
      if (callbacks[i] instanceof WSPasswordCallback)
      {
        WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];


        // DECRYPT (1)
        // Need a password to get the private key of this identifier
        // (username) from the keystore. WSS4J uses this private key to decrypt
        // the session (symmetric) key. Because the encryption method uses the
        // public key to encrypt the session key it needs no password (a public
        // key is usually not protected by a password).
        if (pc.getUsage() == WSPasswordCallback.DECRYPT)
        {
          //pc.setPassword("mypassword");
        }
        // USERNAME_TOKEN (2)
        // Need the password to fill in or to verify a UsernameToken.
        else if (pc.getUsage() == WSPasswordCallback.USERNAME_TOKEN)
        {
          pc.setPassword("mypassword");
        }
        // SIGNATURE (3)
        // Need the password to get the private key of this identifier
        // (username) from the keystore. WSS4J uses this private key to produce
        // a signature. The signature verfication uses the public key to verfiy
        // the signature.
        else if (pc.getUsage() == WSPasswordCallback.SIGNATURE)
        {
          java.io.InputStream is = PWCallback.class.getClassLoader().getResourceAsStream("siri-crypto-keystore.properties");
          java.util.Properties props = new java.util.Properties();
          props.load(is);
          String pwd = props.getProperty("org.apache.ws.security.crypto.merlin.alias.password");
          pc.setPassword((null == pwd)? "" : pwd);
        }
        // KEY_NAME (4)
        // Need the key, not the password, associated with the identifier.
        // WSS4J uses this key to encrypt or decrypt parts of the SOAP request.
        // Note, the key must match the symmetric encryption/decryption
        // algorithm specified (refer to ENC_SYM_ALGO).
        else if (pc.getUsage() == WSPasswordCallback.KEY_NAME)
        {
          pc.setKey(key);
        }
        // USERNAME_TOKEN_UNKNOWN (5)
        // Either an not specified password type or a password type passwordText.
        // In these both cases only the password variable is set. The callback
        // class now may check if the username and password match. If they don't
        // match the callback class must throw an exception. The exception can
        // be a UnsupportedCallbackException or an IOException.
        else if (pc.getUsage() == WSPasswordCallback.USERNAME_TOKEN_UNKNOWN)
        {
          pc.setKey(key);
        }
        else if (pc.getUsage() == WSPasswordCallback.KEY_NAME)
        {
          pc.setKey(key);
        }

        else
        {
          throw new UnsupportedCallbackException(callbacks[i],
          "Unrecognized usage '" + pc.getUsage() + "'");
        }
      }
      else
      {
        throw new UnsupportedCallbackException(callbacks[i],
            "Unrecognized Callback");
      }
    }
  }
}
