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);
}