そのプロバイダ オブジェクトが、StpProvider インターフェイスを実装し、他の CM API インターフェイスを、CM API ライブラリが提供する実装環境に接続します。
CM API ライブラリには、2 つのプロバイダ実装クラスがあります。1 つは、CcProvider インターフェイスを実装し、もう 1 つは CqProvider インターフェイスを実装します。CqProvider 実装クラスは、CqProvider.CQ_ONLY_PROVIDER_CLASS というリテラルを使用して名前が付けられます。 これを ProviderFactory.createProvider メソッドに渡して Rational CM API CqProvider クラスのインスタンスを取得してください。
ProviderFactory.createProvider には、インスタンス化されたプロバイダが認証オブジェクトを取得するために使用する、コールバック オブジェクトも渡す必要があります。認証オブジェクトは、データベースでの操作 (レコードの状態を変更したり、フィールド値を変更するなど) を実行する前に、ユーザーを Rational ClearQuest ユーザーとして認証するために必要な認証をプロバイダに提供します。ユーザーが指定するコールバック オブジェクトを使用することによって、ユーザー認証 (ユーザー名とパスワード) の取得をアプリケーションで完全に管理することができます。認証の取得は、アプリケーションに明示的に設定しておき、開始時にユーザーの求めに応じて行うことも、最初に必要とされたときに行うこともできます。
プロバイダ オブジェクトは、Rational CM API を使用したプログラミングのすべてのユース ケースで必要であるため、このチュートリアルのすべての例では、すべてのアプリケーションで使用するようにユーティリティ クラスで定義された getProvider メソッドを使用します。コールバック オブジェクトもユーティリティ クラス内に定義され、ユーザーが最初にデータベースにアクセスしようとしたときに、ユーザー名とパスワードを要求します。その後は、受け入れ可能であるかぎりそれらの認証を再利用します。
/**
* ユーザーから取得したユーザー名とパスワードを、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 プロバイダのインスタンスを構成します。
*
* @return インスタンス化された CqProvider オブジェクトを戻します
* @throws プロバイダをインスタンス化できなかった場合に
* 例外をスローします
*/
static StpProvider getProvider() throws Exception {
try {
Callback callback = new StpCallback() {
private UnPw m_unpw;
public Authentication getAuthentication(String r, int c)
{ return null; /* 呼び出されません */ }
public Authentication getAuthenticationEx(Domain domain,
String realm,
int retryCount,
StpProvider provider,
WvcmException failure)
throws WvcmException
{
// それぞれの新規リポジトリの最後の認証を再利用を試行します
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));
}
};
// プロバイダをインスタンス化します
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 ダイアログに表示させるためのメソッドを組み込みます。
/**
* Throwable からメッセージの内容を抽出して String の階層配列として戻します。
* その際、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);
}