< Anterior | Próximo >

Obtendo um Provedor

Esta lição do tutorial ilustra as primeiras etapas na utilização do modelo de programação Rational CM API para trabalhar com os recursos Rational ClearQuest.
Antes que você possa recuperar, modificar, criar ou excluir recursos em um repositório do produto, como um banco de dados de usuário do Rational ClearQuest, é necessário primeiro criar uma instância de um objeto do Provedor para esse tipo de repositório do produto.

O objeto do Provedor implementa a interface com o StpProvider e, desta maneira, conecta as outras interfaces do CM API para a implementação fornecida pela biblioteca do CM API.

Há duas classes de implementação do Provedor dentro da biblioteca do CM API; uma implementando a interface do CcProvider e uma implementando a interface do CqProvider. A classe de implementação do CqProvider é denominada pelo literal CqProvider.CQ_ONLY_PROVIDER_CLASS. Passe este para o método ProviderFactory.createProvider para obter uma instância da classe CqProvider do Rational CM API.

Também é necessário fornecer um objeto de Retorno de Chamada ao ProviderFactory.createProvider a partir do qual o Provedor instanciado possa obter objetos de Autenticação. O objeto de Autenticação fornece credenciais ao provedor necessárias para autenticar o usuário como um usuário do Rational ClearQuest antes de executar as operações em um banco de dados (como alterar o estado de um registro ou modificar valores de campo). O uso de um objeto de Retorno de Chamada que você fornecer dá um controle integral a seu aplicativo na aquisição de credenciais do usuário (nome de usuário e senha), que podem ser explicitamente configurados no aplicativo, solicitados do usuário na inicialização ou da primeira vez que seja necessário.

Como um objeto do Provedor é necessário para todos os casos de uso de programação com o Rational CM API, todos os exemplos deste tutorial usam um método getProvider definido na classe Utilitários a ser usada por todos os aplicativos. O objeto de Retorno de Chamada, também definido na classe Utilitários, solicita nome de usuário e senha quando o usuário tenta acessar um banco de dados e, em seguida, continua a reutilizar essas credenciais até quando forem aceitáveis.

/**
 * Um objeto de Autenticação simples no qual o nome de usuário e senha
 * obtidos do usuário são armazenados em cache para uso pela API da Equipe.
 */
static class UnPw implements Authentication {
    /**
     * Constrói um objeto de Autenticação
     * 
     * @param unpw A String[] contendo um nome de usuário e senha.
     */
    UnPw(String[] unpw) {  m_data = unpw; }

    public String loginName() { return m_data[0]; }
    public String password() { return m_data.length > 1 ? m_data[1] : ""; };

    /** As credenciais armazenadas em cache */
    private String[] m_data;
}


/**
 * Constrói uma instância de um provedor CM API para ClearQuest.
 * 
 * @return O objeto CqProvider instanciado
 * @throws Exceção
 *             Se o provedor não puder ser instanciado
 */
static StpProvider getProvider() throws Exception {
    try {
        Callback callback = new StpCallback() {
            private UnPw m_unpw;

            public Authentication getAuthentication(String r, int c)
            {   return null; /* Will not be called */   }

            public Authentication getAuthenticationEx(Domain domain,
                                                      String realm,
                                                      int retryCount,
                                                      StpProvider provider,
                                                      WvcmException failure) 
            throws WvcmException
            {
                // Tente reutilizar as últimas credenciais em cada novo repositório
                if (m_unpw != null && retryCount == 0)
                    return m_unpw;

                String title = "Enter " + domain 
                        + " Username '+' Password for "
                        + realm + " [" + retryCount + "]";
                
                if (failure != null)
                    title = "Login failed: " + failure + "\n" + title;
                
                String unpw = JOptionPane.showInputDialog(title, "admin+");

                if (unpw == null || unpw.length() == 0)
                    throw new IllegalAccessError("User canceled request");
                
                if (unpw.equals("anonymous"))
                    return null;
                
                if (unpw.startsWith("@")) {
                    File file = new File(unpw.substring(1));

                    try {
                        FileReader reader = new FileReader(file);
                        char[] buf = new char[100];
                        int count = reader.read(buf);

                        unpw = new String(buf, 0, count);
                        reader.close();
                    } catch (Throwable t) {
                        Utilities.exception(null,
                                            "Reading password file " + unpw,
                                            t);
                    }
                }

                return m_unpw = new UnPw(unpw.split("\\+", -2));
            }
        };

        // Instantiate a Provider
        return (StpProvider) ProviderFactory
            .createProvider(StpProvider.PROVIDER_CLASS, callback);
    } catch (InvocationTargetException ite) {
        WvcmException e = (WvcmException) ite.getTargetException();

        System.out.println("*** " + e);
        
        for (Throwable nested: e.getNestedExceptions())
            System.out.println("***  " + nested);

        throw e;
    }
}

Neste exemplo nós usamos uma instância da interface do StpProvider.StpCallback estendida, porque são fornecidas mais informações quando a autenticação é solicitada.

Como o Rational CM API relata todos os erros lançando um StpException, nós incluímos na classe Utilitários um método que formata as informações de tal exceção em uma mensagem de texto e exibe-a em um diálogo Swing.

/**
 * Extrai o conteúdo da mensagem de um Throwable e retorna-o como uma
 * matriz hierárquica de Cadeias capturando o aninhamento dos componentes de mensagem Throwable.
 * Esta estrutura formata razoavelmente em uma invocação SWING
 * showMessageDialog.
 * 
 * @param ex O objeto Throwable cujo conteúdo de mensagem deve ser extraído.
 * @return Se o Throwable dado tiver componentes aninhados, uma matriz que consiste na
 *         mensagem do Throwable e uma matriz das mensagens aninhadas.
 */
private static Object messages(Throwable ex) {
    String msg = ex.getLocalizedMessage();

    if (msg == null || msg.length() == 0)
        msg = ex.toString();

    if (ex instanceof StpException) {
        Throwable[] nested = ((StpException) ex).getNestedExceptions();

        if (nested != null && nested.length > 0) {
            Object[] msgs = new Object[nested.length];

            for (int i = 0; i < msgs.length; ++i)
                msgs[i] = messages(nested[i]);

            return new Object[] { msg, msgs };
        }
    } else if (ex.getCause() != null) {
        return new Object[] {msg, new Object[]{messages(ex.getCause())}};
    }

    return msg;
}

/**
 * Exibe um diálogo Swing contendo as mensagens associadas com um
 * Throwable dado.
 * 
 * @param frame O quadro pai para o diálogo da mensagem.
 * @param title O título a aparecer na janela de diálogo.
 * @param ex O throwable cujas mensagens devem ser exibidas.
 */
static void exception(Component frame, String title, Throwable ex) {
    JOptionPane.showMessageDialog(frame,
                                    messages(ex),
                                    title,
                                    JOptionPane.ERROR_MESSAGE);
}
Agora você tem o código para obter um provedor e manipular exceções e pode começar a trabalhar com os recursos disponíveis em um banco de dados de usuário doRational ClearQuest.

Ponto de verificação da lição

As primeiras etapas em gravação de programas com o Rational CM API são para criar um objeto de Retorno de Chamada e para obter um objeto do Provedor a partir do qual você possa trabalhar com recursos específicos ao produto.
Nesta lição, você aprendeu o seguinte:
  • Sobre objetos de Retorno de chamada
  • Sobre objetos do Provedor
  • Sobre a manipulação de exceção no CM API
  • Como usar o CM API para instanciar os objetos de Retorno de Chamada e de Provedor
  • Como usar o CM API para manipulação de exceção
< Anterior | Próximo >

Feedback