Provider 오브젝트는 StpProvider 인터페이스를 구현하고 CM API 라이브러리에서 제공하는 구현으로 다른 CM API 인터페이스를 연결합니다.
CM API 라이브러리에는 CcProvider 인터페이스를 구현하고 CqProvider 인터페이스를 구현하는 두 개의 Provider 구현 클래스가 있습니다. CqProvider 구현 클래스는 리터럴 CqProvider.CQ_ONLY_PROVIDER_CLASS라고 합니다. 이것을 ProviderFactory.createProvider 메소드로 전달하여 Rational CM API CqProvider 클래스의 인스턴스를 얻습니다.
ProviderFactory.createProvider도 인스턴스화된 Provider가 Authentication 오브젝트를 얻을 수 있는 Callback 오브젝트를 지정하는데 필요합니다. Authentication 오브젝트는 데이터베이스에서 오퍼레이션(예: 레코드 상태 변경 또는 필드 값 수정)을 수행하기 전에 사용자를 Rational ClearQuest 사용자로 인증하는데 필요한 신임을 Provider에게 제공합니다. 사용자가 제공하는 Callback 오브젝트를 사용하면 사용자 신임(사용자 이름 및 비밀번호) 확보를 넘어서는 애플리케이션 완전 제어가 가능해지며 시작시 사용자의 요청으로 또는 필요할 때 처음으로 애플리케이션에 명시적으로 설정할 수 있습니다.
Rational CM API의 모든 프로그래밍 유스 케이스에 대해 Provider 오브젝트가 필요하기 때문에 이 학습서의 모든 예제는 모든 애플리케이션에서 사용할 수 있도록 Utilities 클래스에 정의된 getProvider 메소드를 사용합니다. 또한 Utilities 클래스에 정의된 Callback 오브젝트는 사용자가 처음으로 데이터베이스에 액세스를 시도할 때 사용자 이름 및 비밀번호를 요청하고 그 다음 허용되는 한도에서 해당 신임을 계속 재사용합니다.
/** * 사용자의 사용자 이름 및 비밀번호의 단순 인증 오브젝트는 * Team API의 사용을 위해 캐시됩니다. */ static class UnPw implements Authentication { /** * 사용자 이름 및 비밀번호를 포함하는 * * @param unpw A String[] 인증 오브젝트를 생성합니다. */ UnPw(String[] unpw) { m_data = unpw; } public String loginName() { return m_data[0]; } public String password() { return m_data.length > 1 ? m_data[1] : ""; }; /** 캐시된 신임 */ private String[] m_data; } /** * ClearQuest CM API Provider의 인스턴스를 생성합니다. * * @return 초기화된 CqProvider 오브젝트 * @throws 예외 * Provider를 초기화할 수 없는 경우 */ 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 인터페이스를 사용합니다.
Rational CM API가 StpException을 처리하여 모든 오류를 보고하므로 이러한 예외 정보를 텍스트 메시지로 형식화하고 Swing 대화 상자에 표시하는 메소드를 Utilities 클래스에 포함시킵니다.
/** * Throwable로부터 메시지 컨텐츠를 추출하고 * 이를 Throwable 메시지 컴포넌트의 중첩을 캡처하는 * 문자열의 계층 구조 배열로 리턴합니다. 이 구조는 SWING * showMessageDialog 호출을 형식화합니다. * * @param ex 메시지 컨텐츠를 추출할 대상 Throwable 오브젝트. * @return 해당 Throwable 오브젝트에 중첩된 컴포넌트가 있는 경우, * Throwable 메시지로 구성된 배열 및 중첩된 메시지의 배열. */ 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; } /** * 제공된 Throwable과 연관된 메시지를 포함하는 * Swing 대화 상자를 표시합니다. * * @param frame 메시지 대화 상자의 상위 프레임. * @param title 대화 상자 창에 표시되는 제목. * @param ex 메시지가 표시되는 대상 throwable. */ static void exception(Component frame, String title, Throwable ex) { JOptionPane.showMessageDialog(frame, messages(ex), title, JOptionPane.ERROR_MESSAGE); }