L'objet Fournisseur implémente l'interface StpProvider et connecte ainsi les autres interfaces de l'API CM à l'implémentation fournie par la bibliothèque de cette même interface.
La classe d'implémentation CqProvider est nommée par le littéral CqProvider.CQ_ONLY_PROVIDER_CLASS. Transmettez cela à la méthode ProviderFactory.createProvider pour obtenir une instance de la classe CqProvider de l'API CM ClearQuest.
ProviderFactory.createProvider doit également recevoir un objet de rappel à partir duquel le Fournisseur instancié peut obtenir des objets d'authentification. L'objet d'authentification fournit au fournisseur les accréditations nécessaires pour authentifier l'utilisateur en tant qu'utilisateur Rational ClearQuest avant qu'il puisse effectuer des opérations dans une base de données (comme modifier l'état d'un enregistrement ou modifier des valeurs de zones). L'utilisation d'un objet de rappel fourni par vous donne à votre application le contrôle complet sur l'acquisition des accréditations utilisateur (nom d'utilisateur et mot de passe) qui peuvent être définies explicitement dans l'application, sollicitées auprès de l'utilisateur au démarrage ou à la première utilisation.
Un objet Fournisseur étant nécessaire pour tous les cas d'utilisation de la programmation avec l'API CM ClearQuest, tous les exemples de ce tutoriel utilisent une méthode getProvider définie dans la classe Utilitaires qui doit être utilisée par toutes les applications. L'objet de rappel, également défini dans la classe Utilitaires, demande le nom d'utilisateur et le mot de passe lorsque l'utilisateur tente d'accéder à la base de données pour la première fois puis continue à réutiliser ces accréditations aussi longtemps qu'elles sont acceptables.
/** * Un objet d'authentification simple dans lequel le nom d'utilisateur et le mot de passe * sont obtenus de l'utilisateur est placé en mémoire cache par l'API CM ClearQuest. */ La classe statique UnPw implémente l'Authentification { /** * Construit un objet d'authentification * * @param unpw : chaîne[] contenant le nom d'utilisateur et le mot de passe. */ UnPw(String[] unpw) { m_data = unpw; } public String loginName() { return m_data[0]; } public String password() { return m_data.length > 1 ? m_data[1] : ""; }; /** Les accréditations placées en mémoire cache */ private String[] m_data; } /** * Construit une instance d'un fournisseur d'API CM pour ClearQuest. * * @return : l'objet CqProvider instancié * @throws : exception * Si le fournisseur n'a pas pu être instancié */ static StpProvider getProvider() throws Exception { try { Callback callback = new StpCallback() { private UnPw m_unpw; public Authentication getAuthentication(String r, int c) { return null; /* Ne sera pas appelé */ } public Authentication getAuthenticationEx(Domain domain, String realm, int retryCount, StpProvider provider, WvcmException failure) throws WvcmException { // Essaie de réutiliser les dernières accréditations sur chaque nouveau référentiel 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)); } }; // Instancie un fournisseur 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; } }
Dans cet exemple, nous utilisons une instance de l'interface étendue StpProvider.StpCallback parce qu'il est fournit plus d'informations lorsque l'authentification est demandée.
Du fait que l'API CM ClearQuest signale toutes les erreurs en renvoyant une StpException, nous incluons dans la classe Utilitaires une méthode qui met en forme les informations d'une telle exception en un message de texte et les affiche dans une boîte de dialogue Swing.
/** * Extrait le contenu du message d'un objet Throwable et le renvoie sous forme * d'un tableau hiérarchique de chaînes capturant l'imbrication * des composants de message de l'objet Throwable. Cette structure met en forme raisonnablement dans un appel SWING * showMessageDialog. * * @param ex : l'objet de message Throwable dont le contenu de message doit être extrait. * @return : si l'objet Throwable donné comporte des composants imbriqués, un tableau constitué * du message de l'objet Throwable et un tableau des messages imbriqués. */ 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; } /** * Affiche une boîte de dialogue Swing contenant les messages associés avec un * objet Throwable donné. * * @param frame : trame parente de la boîte de dialogue de message. * @param title : titre qui doit apparaître dans la fenêtre de la boîte de dialogue. * @param ex : objet throwable dont les messages doivent être affichés. */ static void exception(Component frame, String title, Throwable ex) { JOptionPane.showMessageDialog(frame, messages(ex), title, JOptionPane.ERROR_MESSAGE); }