El objeto Provider implementa la interfaz StpProvider y por consiguiente, conecta la otras interfaces de la API CM con la implementación que se proporciona en la biblioteca de la API CM.
La clase de implementación CqProvider se identifica mediante el literal CqProvider.CQ_ONLY_PROVIDER_CLASS. Transfiérala al método ProviderFactory.createProvider para obtener una instancia de la clase CqProvider de ClearQuest CM API.
ProviderFactory.createProvider también requiere que se le suministre un objeto Callback desde el cual el objeto Provider para el que se han de crear instancias puede obtener objetos Authentication. El objeto Authentication proporciona al proveedor las credenciales necesarias para autenticar al usuario como un usuario de Rational ClearQuest antes de realizar operaciones en una base de datos (como por ejemplo, cambiar el estado de un registro o modificar los valores de campo). El uso de un objeto Callback que se suministre otorga a la aplicación el control completo sobre la adquisición de credenciales de usuario (nombre de usuario y contraseña), que se pueden definir explícitamente en la aplicación, solicitada por el usuario al iniciar el sistema o la primera vez que sea necesario.
Dado que se necesita un objeto Provider para todos los casos de uso de programación con ClearQuest CM API, todos los ejemplos que se facilitan en esta guía de aprendizaje emplean un método getProvider definido en la clase Utilities que todas las aplicaciones va a utilizar. El objeto Callback, definido también en la clase Utilities, solicita el nombre de usuario y la contraseña cuando el usuario intenta por primera vez acceder a una base de datos y a continuación, sigue volviendo a utilizar dichas credenciales siempre y cuando sean aceptables.
/** * A simple Authentication object in which the username and password * obtained from the user is cached for use by the ClearQuest API. */ static class UnPw implements Authentication { /** * Constructs an Authentication object * * @param unpw A String[] containing the username and 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] : ""; }; /** The cached credentials */ private String[] m_data; } /** * Constructs an instance of a CM API provider for ClearQuest. * * @return The instantiated CqProvider object * @throws Exception * If the provider could not be instantiated */ 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 { // Try to reuse last credentials on each new 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)); } }; // 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; } }
En este ejemplo, utilizamos una instancia de la interfaz StpProvider.StpCallback ampliada porque ofrece más información que cuando se solicita la autenticación.
Dado que ClearQuest CM API informa de todos los errores al emitir una StpExeption, incluimos en la clase Utilities un método que formatea la información en una excepción de este tipo en un mensaje de texto y la visualiza en un diálogo Swing.
/** * Extracts the message content from a Throwable and returns it as a * hierarchical array of Strings capturing the nesting of the Throwable's * message components. This structure formats reasonably in a SWING * showMessageDialog invocation. * * @param ex The Throwable object whose message content is to be extracted. * @return If the given Throwable has nested components, an array consisting * of the Throwable's message and an array of the nested messages. */ 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; } /** * Displays a Swing dialog containing the messages associated with a given * Throwable. * * @param frame The parent frame for the message dialog. * @param title The title to appear in the dialog window. * @param ex The throwable whose messages are to be displayed. */ static void exception(Component frame, String title, Throwable ex) { JOptionPane.showMessageDialog(frame, messages(ex), title, JOptionPane.ERROR_MESSAGE); }