Provider 오브젝트는 StpProvider 인터페이스를 구현하므로 CM API 라이브러리가 제공하는 구현에 다른 CM API 인터페이스를 연결합니다.
CqProvider 구현 클래스는 리터럴 CqProvider.CQ_ONLY_PROVIDER_CLASS로 이름이 지정됩니다. ProviderFactory.createProvider 메소드로 이를 전달하여 ClearQuest CM API CqProvider 클래스의 인스턴스를 확보하십시오.
또한 ProviderFactory.createProvider는 인스턴스화된 제공자가 Authentication 오브젝트를 얻을 수 있는 Callback 오브젝트를 제공해야 합니다. Authentication 오브젝트는 데이터베이스에서 오퍼레이션을 수행하기 전에(예: 레코드의 상태 변경 또는 필드 값 수정) 사용자를 Rational ClearQuest 사용자로 인증하기 위해 필요한 신임 정보를 제공자에게 제공합니다. 제공하는 Callback 오브젝트를 사용하면 애플리케이션에 사용자 신임 정보(사용자 이름 및 비밀번호) 획득에 대한 완전한 제어가 제공됩니다. 신임 정보는 시작 시 또는 처음 필요할 때 사용자에게 요청하여 애플리케이션에 명시적으로 설정될 수 있습니다.
Provider 오브젝트는 ClearQuest CM API를 사용하는 모든 프로그래밍 유스 케이스에 필요하므로 이 학습서에 있는 모든 예제에서는 모든 애플리케이션에서 사용될 유틸리티 클래스에 정의된 getProvider 메소드를 사용합니다. 유틸리티 클래스에도 정의된 Callback 오브젝트는 사용자가 처음 데이터베이스에 액세스할 때 사용자 이름과 비밀번호를 요청하고 승인 가능한 한 계속해서 해당 신임 정보를 재사용합니다.
/** * A simple Authentication object in which the username and password * obtained from the user is cached for use by the ClearQuest CM 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; } }
이 예제에서는 확장된 StpProvider.StpCallback 인터페이스의 인스턴스를 사용합니다. 인증이 요청될 때 더 많은 정보가 제공되기 때문입니다.
ClearQuest CM API는 StpException을 발생시켜 모든 오류를 보고하므로, 이러한 예외 정보를 텍스트 메시지로 형식화하고 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); }