< Indietro | Avanti >

Ottenimento di un provider

Questa lezione dell'esercitazione illustra la prima fase nell'utilizzo del modello di programmazione Rational CM API per la gestione delle risorse Rational ClearQuest.
Prima di poter richiamare, modificare, creare o eliminare le risorse in un repository del prodotto, come ad esempio un database utente Rational ClearQuest, è necessario in primo luogo creare un'istanza di un oggetto Provider per tale tipo di repository del prodotto.

L'oggetto Provider implementa l'interfaccia StpProvider e quindi collega le altre interfacce CM API all'implementazione fornita dalla libreria CM API.

Esistono due classi di implementazione Provider all'interno della libreria CM API; una implementa l'interfaccia CcProvider e l'altra l'interfaccia CqProvider. La classe di implementazione CqProvider viene denominata dal letterale CqProvider.CQ_ONLY_PROVIDER_CLASS. Inoltrare ciò al metodo ProviderFactory.createProvider per ottenere un'istanza della classe CqProvider di Rational CM API.

È inoltre necessario che venga fornito un oggetto Callback a ProviderFactory.createProvider dal quale il Provider, di cui è stata creata un'istanza, può ottenere gli oggetti Authentication. L'oggetto Authentication fornisce al provider le credenziali necessarie per l'autenticazione dell'utente come utente Rational ClearQuest prima di eseguire le operazioni in un database (come ad esempio la modifica dello stato di un record o la modifica dei valori campo). L'utilizzo di un oggetto Callback fornito consente all'applicazione di avere un completo controllo sull'acquisizione delle credenziali utente (nome utente e password), che è possibile impostare in modo esplicito nell'applicazione, su richiesta dell'utente al momento dell'avvio oppure la prima volta in cui è necessario.

Poiché un oggetto Provider è necessario per tutti i casi di utilizzo di programmazione con Rational CM API, tutti gli esempi visualizzati in questa esercitazione utilizzano un metodo getProvider definito nella classe Utilities che tutte le applicazioni devono utilizzare. L'oggetto Callback, definito anche nella classe Utilities, richiede il nome utente e la password quando l'utente tenta in primo luogo di accedere a un database e, quindi, continua a riutilizzare tali credenziali fino a quando sono accettate.

/**
 * Un semplice oggetto Authentication in cui il nome utente e la password
 * ottenuti dall'utente vengono memorizzati nella cache per l'utilizzo da parte di Team API.
 */
static class UnPw implements Authentication {
    /**
     * Crea un oggetto Authentication
     * 
     * @param unpw Una String[] contenente il nome utente e la password.
     */
    UnPw(String[] unpw) {  m_data = unpw; }

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

    /** Le credenziali nella cache */
    private String[] m_data;
}


/**
 * Crea un'istanza di un provider CM API per ClearQuest.
 * 
 * @return L'oggetto CqProvider di cui è stata creata un'istanza
 * @throws Eccezione
 *             Se non è stato possibile creare un'istanza del provider
 */
static StpProvider getProvider() throws Exception {
    try {
        Callback callback = new StpCallback() {
            private UnPw m_unpw;

            public Authentication getAuthentication(String r, int c)
            {   return null; /*Non verrà chiamato */   }

            public Authentication getAuthenticationEx(Domain domain,
                                                      String realm,
                                                      int retryCount,
                                                      StpProvider provider,
                                                      WvcmException failure) 
            throws WvcmException
            {
                // Tentare di riutilizzare le ultime credenziali su ciascun nuovo repository
                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));
            }
        };

        // Creare un'istanza di un 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;
    }
}

In questo esempio, viene utilizzata un'istanza dell'interfaccia StpProvider.StpCallback estesa poiché vengono fornite ulteriori informazioni quando viene richiesta l'autenticazione.

Poiché Rational CM API notifica tutti gli errori generando una StpException, nella classe Utilities viene incluso un metodo che formatta le informazioni in questo tipo di eccezione in un messaggio di testo e le visualizza in una finestra di dialogo Swing.

/**
 * Estrae il contenuto del messaggio da un oggetto Throwable e lo restituisce come
 * array gerarchico di stringhe che catturano la nidificazione dei componenti del
 * messaggio Throwable. Questa struttura viene formattata in modo ragionevole in una chiamata
 * showMessageDialog SWING.
 * 
 * @param ex L'oggetto Throwable il cui contenuto del messaggio deve essere estratto.
 * @return Se l'oggetto Throwable fornito dispone di componenti nidificati, un array costituito
 *         dal messaggio del Throwable e un array di messaggi nidificati.
 */
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;
}

/**
 * Visualizza una finestra di dialogo Swing che contiene i messaggi associati a un determinato
 * Throwable.
 * 
 * @param frame Il frame padre per la finestra di dialogo del messaggio.
 * @param title Il titolo da visualizzare nella finestra di dialogo.
 * @param ex L'oggetto Throwable i cui messaggi devono essere visualizzati.
 */
static void exception(Component frame, String title, Throwable ex) {
    JOptionPane.showMessageDialog(frame,
                                    messages(ex),
                                    title,
                                    JOptionPane.ERROR_MESSAGE);
}
Si dispone ora del codice per l'ottenimento di un provider e la gestione delle eccezioni ed è possibile iniziare a gestire le risorse disponibili in un database utente Rational ClearQuest.

Punto di controllo della lezione

Le prime fasi nella scrittura dei programmi con Rational CM API servono per creare un oggetto Callback e per ottenere un oggetto Provider da cui è possibile gestire le risorse specifiche del prodotto.
In questa lezione, sono state fornite informazioni su quanto segue:
  • Informazioni sugli oggetti Callback
  • Informazioni sugli oggetti Provider
  • Informazioni sulla gestione delle eccezioni in CM API
  • Come utilizzare CM API per creare un'istanza degli oggetti Callback e Provider
  • Come utilizzare CM API per la gestione delle eccezioni

Feedback
< Indietro | Avanti >