監査関連オブジェクトの操作
以下のコード例は、監査関連の操作を示しています。監査機能の概要については、監査を参照してください。
クラスへの監査定義の追加
監査はクラス単位で構成されます。クラスは SubscribableClassDefinition オブジェクトで表されます。あるクラスに関して監査されるイベントは、EventClassDefinition オブジェクトで表されます。監査構成情報は、AuditDefinition オブジェクトに保持され、EventClassDefinition オブジェクトが格納されています。クラスで監査されるイベントごとに、1 つの AuditDefinition オブジェクトがあります。1 つの SubscribableClassDefinition オブジェクトに、1 つ以上の AuditDefinition オブジェクトを含めることができます。
クラスを監査するように構成する方法を以下の手順に示します。
- SubscribableClassDefinition オブジェクトまたは Document クラスなどのサブオブジェクトを取得します。
- CreationEvent などの EventClassDefinition オブジェクトを取得します。
- AuditDefinition オブジェクトを作成します。
- AuditDefinitionList オブジェクトを作成します。
- EventClass などの AuditDefinition オブジェクト・プロパティーを設定します。このプロパティーは EventClassDefinition オブジェクトを使用します。
- AuditDefinition オブジェクトを AuditDefinitionList オブジェクトに追加します。
- クラスで監査するイベントごとに、ステップ 2 から 6 を繰り返します。
- SubscribableClassDefinition オブジェクトの AuditDefinitions プロパティーを AuditDefinitionList オブジェクトに設定します。
以下の Java™ および C# の例では、FloodClaim クラス (Document のサブクラス) の 2 つのイベントを監査するように構成します。各イベントごとに、AuditDefinition オブジェクトが作成されます。システム UpdateEvent の場合、AuditDefinition オブジェクトの FilterExpression プロパティーが設定されます。このプロパティーは、FloodClaim クラスのインスタンスに適用されます。この式は、FloodClaim カスタム・プロパティーの値をテストするものです。FloodClaim インスタンスが更新されると、イベントは、この式が true と評価された場合のみ監査されます。
カスタム・イベントは既に作成されており、GUID で指定します。カスタム・イベントについて詳しくは、「カスタム・イベントの作成および起動」を参照してください。
Java の例
// オブジェクト・ストアで監査が有効なことを確認
if (store.get_AuditLevel()==AuditLevel.NONE)
{
store.set_AuditLevel(AuditLevel.ENABLED);
store.save(RefreshMode.REFRESH);
}
// FloodClaim のクラス定義をフェッチ
DocumentClassDefinition dcd = Factory.DocumentClassDefinition.fetchInstance(
store, new Id("{00A3E7B8-3473-4136-B44C-5A05874E718C}"), null);
// DocumentClassDefinition オブジェクトから AuditDefinitionList を取得
AuditDefinitionList adl = dcd.get_AuditDefinitions();
// システム・イベントと共に設定される AuditDefinition オブジェクトを作成
AuditDefinition ad = Factory.AuditDefinition.createInstance(store);
// システム・イベントの EventClassDefinition を取得
EventClassDefinition ecd = Factory.EventClassDefinition.getInstance(
store, GuidConstants.Class_UpdateEvent);
// システム・イベント用に AuditDefinition オブジェクトにプロパティーを設定
ad.set_EventClass(ecd);
ad.set_AuditSuccess(new Boolean("TRUE"));
ad.set_AuditFailure(new Boolean("TRUE"));
ad.set_IncludeSubclassesRequested(new Boolean("FALSE"));
ad.set_ObjectStateRecordingLevel(ObjectStateRecordingLevel.NONE);
ad.set_FilterExpression("auditLocationCode IN ('NOL', 'SEA', 'NVL')");
ad.set_DisplayName("Flood claim processing");
// システム・イベント用にリストに最初の監査定義を追加
adl.add(ad);
// カスタム・イベントと共に設定される AuditDefinition オブジェクトを作成
AuditDefinition ad2 = Factory.AuditDefinition.createInstance(store);
// カスタム・イベントの EventClassDefinition を取得
EventClassDefinition ecd2 = Factory.EventClassDefinition.getInstance (
store, new Id("{9906D34A-DBE2-415E-B807-6B4CCA65B893}"));
// Set properties on AuditDefinition object for custom event.
ad2.set_EventClass(ecd2);
ad2.set_AuditSuccess(new Boolean("TRUE"));
ad2.set_AuditFailure(new Boolean("TRUE"));
ad2.set_IncludeSubclassesRequested(new Boolean("TRUE"));
ad2.set_ObjectStateRecordingLevel(ObjectStateRecordingLevel.ORIGINAL_AND_MODIFIED_OBJECTS);
ad2.set_DisplayName("Fraudulent claim review");
// カスタム・イベント用にリストに 2 番目の監査定義を追加
adl.add(ad2);
// DocumentClassDefinition オブジェクトに AuditDefinitions プロパティーを設定
dcd.set_AuditDefinitions(adl);
// DocumentClassDefinition オブジェクトを保存
dcd.save(RefreshMode.REFRESH);
C# の例
// オブジェクト・ストアで監査が有効なことを確認
if (store.AuditLevel == AuditLevel.NONE)
{
store.AuditLevel = AuditLevel.ENABLED;
store.Save(RefreshMode.REFRESH);
}
// FloodClaim のクラス定義をフェッチ
IDocumentClassDefinition dcd = Factory.DocumentClassDefinition.FetchInstance(
store, new Id("{00A3E7B8-3473-4136-B44C-5A05874E718C}"), null);
// DocumentClassDefinition オブジェクトから AuditDefinitionList を取得
IAuditDefinitionList adl = dcd.AuditDefinitions;
// システム・イベントと共に設定する監査定義を作成
IAuditDefinition ad = Factory.AuditDefinition.CreateInstance(store);
// システム・イベントの EventClassDefinition を取得
IEventClassDefinition ecd = Factory.EventClassDefinition.GetInstance (
store, GuidConstants.Class_UpdateEvent);
// Set properties on audit definition object for system event.
ad.EventClass = ecd;
ad.AuditSuccess = true;
ad.AuditFailure = true;
ad.IncludeSubclassesRequested = false;
ad.ObjectStateRecordingLevel=ObjectStateRecordingLevel.NONE;
ad.FilterExpression = "auditLocationCode IN ('NOL', 'SEA', 'NVL')";
ad.DisplayName = "Flood claim processing";
// システム・イベント用にリストに最初の監査定義を追加
adl.Add(ad);
// カスタム・イベントと共に設定される AuditDefinition オブジェクトを作成
IAuditDefinition ad2 = Factory.AuditDefinition.CreateInstance(store);
// カスタム・イベントの EventClassDefinition を取得
IEventClassDefinition ecd2 = Factory.EventClassDefinition.GetInstance (
store, new Id("{9906D34A-DBE2-415E-B807-6B4CCA65B893}"));
// Set properties on AuditDefinition object for custom event.
ad2.EventClass = ecd2;
ad2.AuditSuccess = true;
ad2.AuditFailure = true;
ad2.IncludeSubclassesRequested = true;
ad2.ObjectStateRecordingLevel=ObjectStateRecordingLevel.ORIGINAL_AND_MODIFIED_OBJECTS;
ad2.DisplayName = "Fraudulent claim review";
// カスタム・イベント用にリストに 2 番目の監査定義を追加
adl.Add(ad2);
// DocumentClassDefinition オブジェクトに AuditDefinitions プロパティーを設定
dcd.AuditDefinitions = adl;
// DocumentClassDefinition オブジェクトを保存
dcd.Save(RefreshMode.REFRESH);
プロパティーの監査の構成
個々のソース・オブジェクト・プロパティーを監査することにより、監査処理クライアントが、 監査済みイベントからソース・オブジェクトを取得するのではなく、 詳細情報を取得できるようにすることができます。あるイベントのプロパティーの監査を構成するには、次のセクションで説明するように、イベント・クラスとソース・クラスを構成する必要があります。
イベント・クラスの構成
プロパティーの監査のセットアップには、タイプ ObjectChangeEvent のイベント・クラスの構成が 含まれます。PropertyTemplate オブジェクトを使用して、PropertyDefinition カスタム・オブジェクトを 作成し、それをイベント・クラスに追加します。追加された PropertyDefinition オブジェクトごとに、Content Engine は、 対応するプロパティー列を組み込んで Event テーブルを拡張します。このプロパティー列に監査済みのソース・オブジェクト値が保管されます。
イベント・クラスの構成方法を、次の Java および C# の例に示します。2 つのカスタム・プロパティーと 1 つの システム・プロパティーのプロパティー定義が UpdateEvent クラスに追加されます。カスタム・プロパティーとは異なり、システム・プロパティーには、既製のプロパティー・テンプレートはありません。したがって、システム・プロパティーの PropertyDefinition オブジェクトをイベント・クラスに追加するには、PropertyTemplate オブジェクトを作成する必要があります。
Java の例
// オブジェクト変更イベント・クラスを取得
EventClassDefinition ecd = Factory.EventClassDefinition.fetchInstance (
store, GuidConstants.Class_ObjectChangeEvent, null);
// PropertyDefinitions プロパティーをプロパティー・キャッシュから取得
PropertyDefinitionList pdList = ecd.get_PropertyDefinitions();
// カスタム・プロパティー auditLocationCode のプロパティー・テンプレートを取得
PropertyTemplateString ptString = Factory.PropertyTemplateString.getInstance(
store, new Id("{6427183B-6AD9-4C38-8825-ECE7F4D36766}") );
// プロパティー・テンプレートからプロパティー定義を作成
PropertyDefinitionString pdString = (PropertyDefinitionString)ptString.createClassProperty();
// 更新イベントのクラス定義に auditLocationCode を追加
pdList.add(pdString);
// カスタム・プロパティー auditStatus のプロパティー・テンプレートを取得
ptString = Factory.PropertyTemplateString.getInstance (
store, new Id("{8815C41B-4316-482F-82E5-0D2F6540EE1A}") );
// プロパティー・テンプレートからプロパティー定義を作成
pdString = (PropertyDefinitionString)ptString.createClassProperty();
// 更新イベントのクラス定義に auditStatus を追加
pdList.add(pdString);
// 監査対象のシステム・プロパティー LastModifier のプロパティー・テンプレートを作成
ptString = Factory.PropertyTemplateString.createInstance(store);
ptString.set_Cardinality (Cardinality.SINGLE);
LocalizedString locStr = Factory.LocalizedString.createInstance();
locStr.set_LocalizedText ("auditLastModifier");
locStr.set_LocaleName (store.get_LocaleName());
ptString.set_DisplayNames (Factory.LocalizedString.createList());
ptString.get_DisplayNames().add(locStr);
// Save new property template.
ptString.save(RefreshMode.REFRESH);
// プロパティー・テンプレートからプロパティー定義を作成
pdString = (PropertyDefinitionString)ptString.createClassProperty();
// 更新イベントのクラス定義に auditLastModifier を追加
pdList.add(pdString);
// 更新イベント・クラスを保存
ecd.save(RefreshMode.REFRESH);
C# の例
// 更新イベント・クラスを取得
IEventClassDefinition ecd = Factory.EventClassDefinition.FetchInstance (
store, GuidConstants.Class_UpdateEvent, null);
// PropertyDefinitions プロパティーをプロパティー・キャッシュから取得
IPropertyDefinitionList pdList = ecd.PropertyDefinitions;
// カスタム・プロパティー auditLocationCode のプロパティー・テンプレートを取得
IPropertyTemplateString ptString = Factory.PropertyTemplateString.GetInstance(
store, new Id("{6427183B-6AD9-4C38-8825-ECE7F4D36766}"));
// プロパティー・テンプレートからプロパティー定義を作成
IPropertyDefinitionString pdString = (IPropertyDefinitionString)ptString.CreateClassProperty();
// 更新イベントのクラス定義に auditLocationCode を追加
pdList.Add(pdString);
// カスタム・プロパティー auditStatus のプロパティー・テンプレートを取得
ptString = Factory.PropertyTemplateString.GetInstance(
store, new Id("{8815C41B-4316-482F-82E5-0D2F6540EE1A}"));
// プロパティー・テンプレートからプロパティー定義を作成
pdString = (IPropertyDefinitionString)ptString.CreateClassProperty();
// 更新イベントのクラス定義に auditStatus を追加
pdList.Add(pdString);
// 監査対象のシステム・プロパティー LastModifier のプロパティー・テンプレートを作成
ptString = Factory.PropertyTemplateString.CreateInstance(store);
ptString.Cardinality=Cardinality.SINGLE;
ILocalizedString locStr = Factory.LocalizedString.CreateInstance();
locStr.LocalizedText="auditLastModifier";
locStr.LocaleName = store.LocaleName;
ptString.DisplayNames = Factory.LocalizedString.CreateList();
ptString.DisplayNames.Add(locStr);
// Save new property template.
ptString.Save(RefreshMode.REFRESH);
// プロパティー・テンプレートからプロパティー定義を作成
pdString = (IPropertyDefinitionString)ptString.CreateClassProperty();
// 更新イベントのクラス定義に auditLastModifier を追加
pdList.Add(pdString);
// 更新イベント・クラスを保存
ecd.Save(RefreshMode.REFRESH);
ソース・クラスの構成
プロパティーの監査をセットアップするようにイベント・クラスを構成する以外に、監査対象のプロパティーを 保持するソース・クラスも構成する必要があります。監査対象のプロパティーは、イベント・クラスに追加された PropertyDefinition オブジェクトに 対応しなければなりません。
ソース・クラスを構成する Java および C# の例では、このクラスが UpdateEvent オブジェクト用に構成された監査定義を保持することが前提となります。2 つのカスタム・プロパティーと 1 つのシステム・プロパティーのプロパティー定義がこのクラスでの 監査用に構成されます。つまり、PropertyDefinition オブジェクトごとに、 そのオブジェクトの AuditAs プロパティーが、対応するイベント・クラスの PropertyDefinition オブジェクトの作成に使用された PropertyTemplate オブジェクトに設定されます。
Java の例
// Document のサブクラス FloodClaim を取得
DocumentClassDefinition dcd = Factory.DocumentClassDefinition.fetchInstance (
store, new Id("{00A3E7B8-3473-4136-B44C-5A05874E718C}"),null);
// PropertyDefinitions プロパティーをプロパティー・キャッシュから取得
PropertyDefinitionList pdList = dcd.get_PropertyDefinitions();
// カスタム・プロパティー auditLocationCode のプロパティー・テンプレートを取得
PropertyTemplateString auditLocationCode = Factory.PropertyTemplateString.getInstance (
store, new Id("{6427183B-6AD9-4C38-8825-ECE7F4D36766}") );
// カスタム・プロパティー auditStatus のプロパティー・テンプレートを取得
PropertyTemplateString auditStatus = Factory.PropertyTemplateString.getInstance (
store, new Id("{8815C41B-4316-482F-82E5-0D2F6540EE1A}") );
//システム・プロパティー LastModifier のプロパティー・テンプレートを取得
PropertyTemplateString auditLastModifier = Factory.PropertyTemplateString.getInstance (
store, new Id("{F9BA4605-3B96-4CD0-B7B2-8DF64DBE175B}") );
// リストを反復処理して監査のターゲットとなるプロパティー定義を検索
// プロパティー・テンプレートに AuditAs プロパティーを設定
Iterator iter = pdList.iterator();
PropertyDefinition pd = null;
while (iter.hasNext())
{
pd = (PropertyDefinition) iter.next();
// Get SymbolicName property from the property cache.
String pdSymbolicName;
pdSymbolicName = pd.get_SymbolicName();
if (pdSymbolicName.equalsIgnoreCase("auditLocationCode"))
{
System.out.println(pdSymbolicName + " found");
pd.set_AuditAs(auditLocationCode);
}
if (pdSymbolicName.equalsIgnoreCase("auditStatus"))
{
System.out.println(pdSymbolicName + " found");
pd.set_AuditAs(auditStatus);
}
if (pdSymbolicName.equalsIgnoreCase("LastModifier"))
{
System.out.println("pdSymbolicName + " found");
pd.set_AuditAs(auditLastModifier);
}
}
// FloodClaim クラスを保存
dcd.save(RefreshMode.REFRESH);
C# の例
// Document のサブクラス FloodClaim を取得
IDocumentClassDefinition dcd = Factory.DocumentClassDefinition.FetchInstance (
store, new Id("{00A3E7B8-3473-4136-B44C-5A05874E718C}"),null);
// PropertyDefinitions プロパティーをプロパティー・キャッシュから取得
IPropertyDefinitionList pdList = dcd.PropertyDefinitions;
// カスタム・プロパティー auditLocationCode のプロパティー・テンプレートを取得
IPropertyTemplateString auditLocationCode = Factory.PropertyTemplateString.GetInstance(
store, new Id("{6427183B-6AD9-4C38-8825-ECE7F4D36766}") );
// カスタム・プロパティー auditStatus のプロパティー・テンプレートを取得
IPropertyTemplateString auditStatus = Factory.PropertyTemplateString.GetInstance(
store, new Id("{8815C41B-4316-482F-82E5-0D2F6540EE1A}") );
//システム・プロパティー LastModifier のプロパティー・テンプレートを取得
IPropertyTemplateString auditLastModifier = Factory.PropertyTemplateString.GetInstance(
store, new Id("{F9BA4605-3B96-4CD0-B7B2-8DF64DBE175B}") );
// リストを反復処理して監査のターゲットとなるプロパティー定義を検索
// プロパティー・テンプレートに AuditAs プロパティーを設定
foreach (IPropertyDefinition pd in pdList)
{
String pdSymbolicName;
pdSymbolicName = pd.SymbolicName;
if (pdSymbolicName.Equals("auditLocationCode"))
{
System.Console.WriteLine("Property definition selected: " + pdSymbolicName);
pd.AuditAs=auditLocationCode;
}
if (pdSymbolicName.Equals("auditStatus"))
{
System.Console.WriteLine("Property definition selected: " + pdSymbolicName);
pd.AuditAs=auditStatus;
}
if (pdSymbolicName.Equals("LastModifier"))
{
System.Console.WriteLine("Property definition selected: " + pdSymbolicName);
pd.AuditAs=auditLastModifier;
}
}
// FloodClaim クラスを保存
dcd.Save(RefreshMode.REFRESH);
監査廃棄の構成
監査廃棄のバックグラウンド・スレッドを構成するには、サーバー階層の 1 つ以上のオブジェクトに監査構成を 設定し、さらに 1 つのオブジェクト・ストアに 1 つ以上の監査廃棄ポリシーを設定する必要があります。
監査構成の設定
CmAuditingConfiguration を設定して 監査廃棄サブシステムを構成する方法を、次の Java および C# の例に示します。コードは、ドメイン作成時に生成された CmAuditingConfiguration の デフォルト・インスタンスにプロパティーを設定します。デフォルト・インスタンスは、最初は無効になっている点に注意してください。
Java の例
CmAuditingConfiguration auditConfig = null;
// ドメインに対する PropertyFilter を作成
PropertyFilter pf = new PropertyFilter();
pf.addIncludeProperty(new FilterElement(null, null, null, "SubsystemConfigurations", null));
// デフォルト・ドメインを取得
Domain domain = Factory.Domain.fetchInstance(ceConn, null, pf);
// Get domain's subsystem configurations,
// and iterate to get the default auditing configuration.
SubsystemConfigurationList sclist = domain.get_SubsystemConfigurations();
Iterator it = sclist.iterator();
while (it.hasNext())
{
SubsystemConfiguration subsystemConfig = (SubsystemConfiguration) it.next();
if (subsystemConfig.getClassName().equals("CmAuditingConfiguration") )
{
auditConfig = (CmAuditingConfiguration) subsystemConfig;
break;
}
}
// Create CmTimeslotList object.
CmTimeslotList tsList = Factory.CmTimeslot.createList();
// その 1。CmTimeslot オブジェクトを作成し、
// 監査廃棄が毎週水曜日の午前 2 時から 4 時間
// 実行されるように構成
CmTimeslot ts1 = Factory.CmTimeslot.createInstance();
ts1.set_Weekday(Weekday.WEDNESDAY);
ts1.set_Duration(Integer.valueOf(240)); // 4 時間
ts1.set_StartMinutesPastMidnight(Integer.valueOf(120));
// その 2。CmTimeslot オブジェクトを作成し、
// 監査廃棄が毎週末の土曜日深夜 12 時から 48 時間
// 実行されるように構成
CmTimeslot ts2 = Factory.CmTimeslot.createInstance();
ts2.set_Weekday(Weekday.SATURDAY);
ts2.set_Duration(Integer.valueOf(2880));// 48 時間
ts2.set_StartMinutesPastMidnight(Integer.valueOf(0));
// CmTimeslot オブジェクトをリストに追加
tsList.add(ts1);
tsList.add(ts2);
// CmAuditingConfiguration にタイム・スロットを設定し、このオブジェクトを有効化
auditConfig.set_AuditDispositionTimeslots(tsList);
auditConfig.set_AuditDispositionEnabled(Boolean.TRUE);
// 更新済みの CmAuditingConfiguration オブジェクトをリストに追加し、
// リストをドメインに設定
sclist.add(auditConfig);
domain.set_SubsystemConfigurations(sclist);
// ドメインを保存
domain.save(RefreshMode.REFRESH);
C# の例
ICmAuditingConfiguration auditConfig = null;
// ドメインに対する PropertyFilter を作成
PropertyFilter pf = new PropertyFilter();
pf.AddIncludeProperty(new FilterElement(null, null, null, "SubsystemConfigurations", null));
// デフォルト・ドメインを取得
IDomain domain = Factory.Domain.FetchInstance(ceConn, null, pf);
// Get domain's subsystem configurations,
// and iterate to get the default auditing configuration.
ISubsystemConfigurationList sclist = domain.SubsystemConfigurations;
foreach (ISubsystemConfiguration subsystemConfig in sclist)
{
if (subsystemConfig.GetClassName().Equals("CmAuditingConfiguration") )
{
auditConfig = (ICmAuditingConfiguration) subsystemConfig;
break;
}
}
// ICmTimeslotList オブジェクトを作成
ICmTimeslotList tsList = Factory.CmTimeslot.CreateList();
// その 1。CmTimeslot オブジェクトを作成し、
// 監査廃棄が毎週水曜日の午前 2 時から 4 時間
// 実行されるように構成
ICmTimeslot ts1 = Factory.CmTimeslot.CreateInstance();
ts1.Weekday=Weekday.WEDNESDAY;
ts1.Duration=240; // 4 時間
ts1.StartMinutesPastMidnight = 120;
// その 2。CmTimeslot オブジェクトを作成し、
// 監査廃棄が毎週末の土曜日深夜 12 時から 48 時間
// 実行されるように構成
ICmTimeslot ts2 = Factory.CmTimeslot.CreateInstance();
ts2.Weekday=Weekday.SATURDAY;
ts2.Duration = 2880;// 48 時間
ts2.StartMinutesPastMidnight = 0;
// CmTimeslot オブジェクトをリストに追加
tsList.Add(ts1);
tsList.Add(ts2);
// ICmAuditingConfiguration にタイム・スロットを設定し、このオブジェクトを有効化
auditConfig.AuditDispositionTimeslots=tsList;
auditConfig.AuditDispositionEnabled=true;
// 更新済みの CmAuditingConfiguration オブジェクトをリストに追加し、
// リストをドメインに設定
sclist.Add(auditConfig);
domain.SubsystemConfigurations=sclist;
// ドメインを保存
domain.Save(RefreshMode.REFRESH);
オブジェクト・ストア・ポリシーの設定
オブジェクト・ストアに CmAuditDispositionPolicy オブジェクトを 設定する方法を、次の Java および C# の例に示します。このオブジェクトの廃棄ルールは、オブジェクト・ストアの監査済みイベント・レコードに 対して適用される選択条件を指定します。これをアクティブ化すると、廃棄スレッドは更新イベントを 3 カ月後に削除します。
Java の例
// ポリシー・オブジェクトを作成する
CmAuditDispositionPolicy auditPolicy = Factory.CmAuditDispositionPolicy.createInstance(
store, ClassNames.CM_AUDIT_DISPOSITION_POLICY);
// 表示名を設定してポリシーを有効化
auditPolicy.set_DisplayName("DeleteUpdateEventsAfter3Months");
auditPolicy.set_IsEnabled(Boolean.TRUE);
// 廃棄ルールを設定
String rule = "IsClass(source, UpdateEvent) AND DateCreated < NOW() - TimeSpan(90,'days')";
auditPolicy.set_DispositionRule(rule);
// ポリシー・オブジェクトを保存
auditPolicy.save(RefreshMode.REFRESH);
C# の例
// ポリシー・オブジェクトを作成する
ICmAuditDispositionPolicy auditPolicy = Factory.CmAuditDispositionPolicy.CreateInstance(
store, ClassNames.CM_AUDIT_DISPOSITION_POLICY);
// 表示名を設定してポリシーを有効化
auditPolicy.DisplayName = "DeleteUpdateEventsAfter3Months";
auditPolicy.IsEnabled = true;
// 廃棄ルールを設定
String rule = "IsClass(source, UpdateEvent) AND DateCreated < NOW() - TimeSpan(90,'days')";
auditPolicy.DispositionRule = rule;
// ポリシー・オブジェクトを保存
auditPolicy.Save(RefreshMode.REFRESH);
クラスからの監査定義の取得
SubscribableClassDefinition オブジェクトから派生したオブジェクトの AuditDefinitions プロパティーを取得することにより、クラスを対象に定義された監査定義を取得できます。戻り値は、AuditDefinition オブジェクトのリストです。AuditDefinition オブジェクトのリストを反復処理することにより、クラスで監査対象として構成されているイベントを検索できます。
監査定義を取得する例は、あるクラスに対して特定の監査イベントが構成されているかどうかを確認するケースです。次の Java および C# のコード例では、DocumentClassDefinition オブジェクトで表した FloodClaim サブクラスを、GUID で指定したカスタム・イベントについて調べます。FloodClaim クラスに対して、このカスタム・イベントの監査が構成されている場合、このコードにより監査対象のカスタム・イベントに関する構成情報が出力されます。
Java の例
// FloodClaim のクラス定義をフェッチ
DocumentClassDefinition dcd = Factory.DocumentClassDefinition.fetchInstance (
store, new Id("{00A3E7B8-3473-4136-B44C-5A05874E718C}"), null);
// Get list of AuditDefinition objects configured for the FloodClaim class,
// これを反復処理。各 AuditDefinition オブジェクトを
// カスタム・イベントに対し、テスト
AuditDefinitionList adl=dcd.get_AuditDefinitions();
Iterator adlIter = adl.iterator();
while (adlIter.hasNext())
{
AuditDefinition ad = (AuditDefinition) adlIter.next();
EventClassDefinition ecd = ad.get_EventClass();
if (ecd.get_Id().equals(new Id("{9906D34A-DBE2-415E-B807-6B4CCA65B893}")))
{
System.out.println (
"Audited class is " + dcd.get_DisplayName() + "¥n" +
"Audited custom event is " + ecd.get_DisplayName() + "¥n" +
"Audit successes? " + ad.get_AuditSuccess() + "¥n" +
"Audit failures? " + ad.get_AuditFailure() + "¥n" +
"Audit subclasses? " + ad.get_IncludeSubclassesRequested() + "¥n" +
"Recording level? " + ad.get_ObjectStateRecordingLevel()
);
}
}
C# の例
// FloodClaim のクラス定義を取得
IDocumentClassDefinition dcd = Factory.DocumentClassDefinition.FetchInstance (
store, new Id("{00A3E7B8-3473-4136-B44C-5A05874E718C}"), null);
// Get list of AuditDefinition objects configured for the FloodClaim class,
// これを反復処理。各 AuditDefinition オブジェクトをカスタム・イベントに対し、テスト
IAuditDefinitionList adl = dcd.AuditDefinitions;
foreach (IAuditDefinition ad in adl)
{
IEventClassDefinition ecd = ad.EventClass;
if (ecd.Id.Equals(new Id("{9906D34A-DBE2-415E-B807-6B4CCA65B893}")))
{
System.Console.WriteLine
(
"Audited class is " + dcd.Name + "¥n" +
"Audited custom event is " + ecd.DisplayName + "¥n" +
"Audited successes? " + ad.AuditSuccess + "¥n" +
"Audited failures? " + ad.AuditFailure + "¥n" +
"Audit subsclasses? " + ad.IncludeSubclassesRequested + "¥n" +
"Recording level? " + ad.ObjectStateRecordingLevel
);
}
}
オブジェクトからの監査履歴の取得
AuditedEvents プロパティーがあるクラスのインスタンスについて、監査履歴を取得できます。(履歴または分析情報については、監査イベント・ログに対して照会を実行することもできます。) 以下の Java および C# のコード例では、Document オブジェクトの AuditedEvents プロパティーを取得し、次に EventSet コレクションの各 Event オブジェクトについてプロパティー値を出力します。
Document オブジェクトは FloodClaim クラスのインスタンスであり、更新イベントの監査用に個々のプロパティーが構成され、Event テーブルがソース・オブジェクト・プロパティーを組み込むように拡張されていることに注意してください。したがって、 以下の例に示すように、返された監査済みイベントからソース・オブジェクト・プロパティーを取得できます。
Java の例
// 監査履歴を取得する Document オブジェクトを取得
Document doc=Factory.Document.fetchInstance(store, new Id("{7AFAC25E-D27B-49A8-B31C-E555EC87608A}"),null);
// Document オブジェクトに対して発行された監査イベントを取得
EventSet es = doc.get_AuditedEvents();
// EventSet コレクションが空でなければ、Document オブジェクトに対して
// 発行されたイベントに対して反復処理
if (!es.isEmpty())
{
Iterator esIter = es.iterator();
while (esIter.hasNext())
{
Event event = (Event) esIter.next();
System.out.println(
"Event is " + event.getClassName() + "¥n" +
"Event ID is " + event.get_Id().toString()+ "¥n" +
"Event initiator is " + event.get_InitiatingUser() + "¥n" +
"Event date is " + event.get_DateCreated().toString() + "¥n" +
"Source object properties extended on event:"+ "¥n" +
" auditLocationCode: " + event.getProperties().getStringValue("auditLocationCode") + "¥n" +
" auditStatus: " + event.getProperties().getStringValue("auditStatus") + "¥n" +
" auditLastModifier: " + event.getProperties().getStringValue("auditLastModifier")+ "¥n" +
"==================================="
);
}
}
else System.out.println("No audited events have been fired for this object");
C# の例
// 監査履歴を取得する Document オブジェクトを取得
IDocument doc = Factory.Document.FetchInstance (
store, new Id("{7AFAC25E-D27B-49A8-B31C-E555EC87608A}"), null);
// Document オブジェクトに対して発行された監査イベントを取得
IEventSet es = doc.AuditedEvents;
// EventSet コレクションが空でなければ、Document オブジェクトに対して発行されたイベントに対して反復処理
if (!es.IsEmpty())
{
foreach (IEvent docEvent in es)
{
System.Console.WriteLine
(
"Event is " + docEvent.GetClassName() + "¥n" +
"Event ID is " + docEvent.Id.ToString() + "¥n" +
"Event initiator is " + docEvent.InitiatingUser + "¥n" +
"Event date is " + docEvent.DateCreated.ToString() + "¥n" +
"Source object properties extended on event:" + "¥n" +
" auditLocationCode: " + docEvent.Properties.GetStringValue("auditLocationCode") + "¥n" +
" auditStatus: " + docEvent.Properties.GetStringValue("auditStatus") + "¥n" +
" auditLastModifier: " + docEvent.Properties.GetStringValue("auditLastModifier")+ "¥n" +
"==================================="
);
}
}
else
{
System.Console.WriteLine("No audited events have been fired for this object");
}
監査イベント・ログの照会
監査イベント・ログに対して照会を実行することができます。監査イベント・ログは、オブジェクト・ストアのデータベースの Event テーブルです。ログに対して照会を実行する最も簡単な方法は、Administration Console for Content Platform Engine を使用する方法です。これを使用すると、SQL 検索を作成することも、検索テンプレートを開始することもできます。しかし、Content Java の API および .NET の API を使用して監査ログを操作することもできます。
API には、アドホック検索用に設計された照会クラスが含まれており、これにより SQL ステートメントを Content Engine に渡すことができます。以下に示す Java および C# の例では、SearchSQL オブジェクトは、指定された値と同等のソース・オブジェクト・プロパティーを保持するイベントを検索する SQL ステートメント文字列で構成されます。検索を実行するために、SearchScope オブジェクトに対する fetchRows 呼び出しで SearchSQL オブジェクトが渡されます。次に、SQL ステートメントの 条件を満たす監査済みイベントごとに、プロパティー値が出力されます。
概要については、照会を参照してください。いずれのプロパティーが検索可能、選択可能、および並べ替え可能であるかについては、「Event プロパティー」で各プロパティーのメタデータを参照してください。照会済みのイベントからソース・オブジェクトを取得する方法を示すコード例については、ソース・オブジェクトの取得を参照してください。
Java の例
// SQL 選択ステートメントを作成し、監査用に構成されたソース・オブジェクト・プロパティーを含める
String sqlString = "SELECT " + PropertyNames.DATE_LAST_MODIFIED + "," +
"auditLastModifier" + "," + "auditLocationCode" + "," + "auditStatus";
// 監査済みソース・オブジェクト・プロパティーを組み込んで拡張されたイベントを検索する SearchSQL オブジェクトを構成
SearchSQL sql = new SearchSQL(sqlString + " FROM Event" +
" WHERE " + "auditStatus IN ('Opened', 'Closed')" +
" ORDER BY " + "auditLocationCode" + "," + PropertyNames.DATE_LAST_MODIFIED);
// 検索操作を実行
SearchScope ss = new SearchScope(store);
RepositoryRowSet rrc = ss.fetchRows(sql, null, null, null);
// 反復処理し、検索結果を出力
Iterator it = rrc.iterator();
while (it.hasNext())
{
RepositoryRow rr = (RepositoryRow) it.next();
System.out.println
(
"Location Code: " + rr.getProperties().getStringValue("auditLocationCode") + "¥n" +
"Claim Status: " + rr.getProperties().getStringValue("auditStatus") + "¥n" +
"Date: " + rr.getProperties().getDateTimeValue(PropertyNames.DATE_LAST_MODIFIED)+ "¥n" +
"Adjuster: " + rr.getProperties().getStringValue("auditLastModifier") + "¥n" +
"==================================="
);
}
C# の例
// SQL 選択ステートメントを作成し、監査用に構成されたソース・オブジェクト・プロパティーを含める
string sqlString = "SELECT " + PropertyNames.DATE_LAST_MODIFIED + "," +
"auditLastModifier" + "," + "auditLocationCode" + "," + "auditStatus";
// 監査済みソース・オブジェクト・プロパティーを組み込んで拡張されたイベントを検索する SearchSQL オブジェクトを構成
SearchSQL sql = new SearchSQL(sqlString + " FROM Event" +
" WHERE " + "auditStatus IN ('Opened', 'Closed')" +
" ORDER BY " + "auditLocationCode" + "," + PropertyNames.DATE_LAST_MODIFIED);
// 検索操作を実行
SearchScope ss = new SearchScope(store);
IRepositoryRowSet rrc = ss.FetchRows(sql, null, null, null);
// 反復処理し、検索結果を出力
foreach (IRepositoryRow rr in rrc)
{
System.Console.WriteLine
(
"Location Code: " + rr.Properties.GetStringValue("auditLocationCode") + "¥n" +
"Claim Status: " + rr.Properties.GetStringValue("auditStatus") + "¥n" +
"Date: " + rr.Properties.GetDateTimeValue(PropertyNames.DATE_LAST_MODIFIED) + "¥n" +
"Adjuster: " + rr.Properties.GetStringValue("auditLastModifier") + "¥n"
);
}
監査ブックマークの使用
CmAuditProcessingBookmark オブジェクト (Content Engine で監査廃棄が有効である時に監査処理クライアントが実行するアクション) を設定する方法を、次の Java および C# の例に示します。FloodClaims ブックマークが存在する場合、これはクライアントが前に監査ログ (Event テーブル) を処理したことを示しており、次にクライアントは、このブックマークの LastProcessed プロパティーによって判別される、監査ログが最後に読み取られたポイントで、このログの処理を開始します。クライアントは、現行セッションの処理を完了すると、LastProcessed プロパティーを更新し、"FloodClaims" ブックマークを保存します。
Java の例
CmAuditProcessingBookmark bookmark = null;
Double lastProcessedRecord = new Double(0);
Id bookmarkId = null;
Boolean bookmarkExist = Boolean.FALSE;
// オブジェクト・ストアから既存のブックマークを取得し、
// "FloodClaims" ブックマークを検索するために反復処理
CmAuditProcessingBookmarkSet bookmarks = store.get_AuditProcessingBookmarks();
Iterator it = bookmarks.iterator();
while (it.hasNext())
{
bookmark = (CmAuditProcessingBookmark) it.next();
System.out.println("Bookmark name is " + bookmark.get_DisplayName() );
if (bookmark.get_DisplayName().equals("FloodClaims") )
{
bookmarkExist = Boolean.TRUE;
// If "FloodClaims" bookmark exists, get the audit sequence number of the last processed record;
lastProcessedRecord = bookmark.get_LastProcessed();
break;
}
}
// "FloodClaims" ブックマークが存在しない場合はこれを作成
if (bookmarkExist == Boolean.FALSE)
{
bookmark = Factory.CmAuditProcessingBookmark.createInstance(store,
ClassNames.CM_AUDIT_PROCESSING_BOOKMARK);
bookmark.set_DisplayName("FloodClaims");
}
// SQL 選択ステートメントを作成し、監査用に構成されたソース・オブジェクト・プロパティーを含める
String sqlString = "SELECT " + PropertyNames.DATE_LAST_MODIFIED + "," +
"auditLastModifier" + "," + "auditLocationCode" + "," + "auditStatus";
// 監査済みソース・オブジェクト・プロパティーを組み込んで拡張されたイベントを検索する SearchSQL オブジェクトを構成
// 既に処理済みのイベントを除く
SearchSQL sql = new SearchSQL(sqlString + " FROM Event" +
" WHERE " + PropertyNames.CM_AUDIT_SEQUENCE + ">" + lastProcessedRecord +
" AND " + "auditStatus IN ('Opened', 'Closed')" +
" ORDER BY " + "auditLocationCode" + "," + PropertyNames.DATE_LAST_MODIFIED);
// 検索操作を実行
SearchScope ss = new SearchScope(store);
RepositoryRowSet rrc = ss.fetchRows(sql, null, null, null);
// 反復処理し、検索結果を出力
Iterator it = rrc.iterator();
while (it.hasNext())
{
RepositoryRow rr = (RepositoryRow) it.next();
System.out.println
(
"Location Code: " + rr.getProperties().getStringValue("auditLocationCode") + "¥n" +
"Claim Status: " + rr.getProperties().getStringValue("auditStatus") + "¥n" +
"Date: " + rr.getProperties().getDateTimeValue(PropertyNames.DATE_LAST_MODIFIED)+ "¥n" +
"Adjuster: " + rr.getProperties().getStringValue("auditLastModifier") + "¥n" +
"==================================="
);
// Update lastProcessedRecord.
lastProcessedRecord = rr.getProperties().getFloat64Value(PropertyNames.CM_AUDIT_SEQUENCE);
}
// 最後に処理されたレコードの監査シーケンス番号を使用してブックマークを更新
bookmark.set_LastProcessed(lastProcessedRecord);
// ブックマークを保存
bookmark.save(RefreshMode.REFRESH);
C# の例
ICmAuditProcessingBookmark bookmark;
Double lastProcessedRecord = 0;
Id bookmarkId = null;
Boolean bookmarkExist = false;
// オブジェクト・ストアから既存のブックマークを取得し、
// "FloodClaims" ブックマークを検索するために反復処理
ICmAuditProcessingBookmarkSet bookmarks = store.AuditProcessingBookmarks;
foreach (ICmAuditProcessingBookmark bookmarkItem in bookmarks)
{
System.Console.WriteLine("Bookmark name is " + bookmarkItem.DisplayName);
if (bookmarkItem.DisplayName.Equals("FloodClaims"))
{
bookmarkExist = true;
bookmark = bookmarkItem;
// If "FloodClaims" bookmark exists, get the audit sequence number of the last processed record;
lastProcessedRecord = (Double) bookmark.LastProcessed;
break;
}
}
// "FloodClaims" ブックマークが存在しない場合はこれを作成
if (bookmarkExist == false)
{
bookmark = Factory.CmAuditProcessingBookmark.CreateInstance(store,
ClassNames.CM_AUDIT_PROCESSING_BOOKMARK);
bookmark.DisplayName = "FloodClaims";
}
// SQL 選択ステートメントを作成し、監査用に構成されたソース・オブジェクト・プロパティーを含める
String sqlString = "SELECT " + PropertyNames.DATE_LAST_MODIFIED + "," +
"auditLastModifier" + "," + "auditLocationCode" + "," + "auditStatus";
// 監査済みソース・オブジェクト・プロパティーを組み込んで拡張されたイベントを検索する SearchSQL オブジェクトを構成
// 既に処理済みのイベントを除く
SearchSQL sql = new SearchSQL(sqlString + " FROM Event" +
" WHERE " + PropertyNames.CM_AUDIT_SEQUENCE + ">" + lastProcessedRecord +
" AND " + "auditStatus IN ('Opened', 'Closed')" +
" ORDER BY " + "auditLocationCode" + "," + PropertyNames.DATE_LAST_MODIFIED);
// 検索操作を実行
SearchScope ss = new SearchScope(store);
IRepositoryRowSet rrc = ss.FetchRows(sql, null, null, null);
// 反復処理し、検索結果を出力
foreach (IRepositoryRow rr in rrc)
{
System.Console.WriteLine
(
"Location Code: " + rr.Properties.GetStringValue("auditLocationCode") + "¥n" +
"Claim Status: " + rr.Properties.GetStringValue("auditStatus") + "¥n" +
"Date: " + rr.Properties.GetDateTimeValue(PropertyNames.DATE_LAST_MODIFIED) + "¥n" +
"Adjuster: " + rr.Properties.GetStringValue("auditLastModifier") + "¥n" +
"==================================="
);
// Update lastProcessedRecord.
lastProcessedRecord = (Double) rr.Properties.GetFloat64Value(PropertyNames.CM_AUDIT_SEQUENCE);
}
// 最後に処理されたレコードの監査シーケンス番号を使用してブックマークを更新
bookmark.LastProcessed = lastProcessedRecord;
// ブックマークを保存
bookmark.Save(RefreshMode.REFRESH);
ソース・オブジェクトの取得
AuditDefinition を構成して、 イベントのソース・オブジェクト (イベントが起動されるオブジェクト) を記録できます。イベントの起動時に、ソース・オブジェクトは他のイベント情報と共に監査イベント・ログ (データベースの Event テーブル) に永続化されます。
ソース・オブジェクトの監査済みイベントへの格納に必要な追加のデータベース領域を制御するため、AuditDefinition.ObjectStateRecordingLevel プロパティーを使用してソース・オブジェクトの記録レベルを構成できます。記録レベルには、ORIGINAL_AND_MODIFIED_OBJECTS (元のイベント前オブジェクトと変更されたイベント後のオブジェクトの両方が記録されます)、MODIFIED_OBJECT (変更されたイベント後のオブジェクトのみ記録されます)、および NONE (ソース・オブジェクトは記録されません) があります。NONE を指定すると、イベントの ModifiedProperties プロパティーも空になります。この値がイベントの SourceObject プロパティーから派生するためです。
監査イベント・ログからソース・オブジェクトを取得する方法を、次の Java および C# の例に示します。SQL ステートメントでは、特定の年齢のチェックイン・イベントをログから取得することを指定しており、変更されたソース・オブジェクトと元のソース・オブジェクトのプロパティーが指定されています。検索の実行後に、コードによって結果が反復処理されます。監査済みの各 Event オブジェクトについて、イベントおよびイベントのソース・オブジェクト (ある場合) に関する情報が出力されます。変更されたソース・オブジェクトのみ記録されたイベント、またはソース・オブジェクトが記録されなかったイベントも確認されます。
Java の例
// SQL 選択ステートメントを作成する
String sqlString = "SELECT " + PropertyNames.ID +"," + PropertyNames.DATE_CREATED + "," +
PropertyNames.EVENT_STATUS + "," + PropertyNames.ORIGINAL_OBJECT + "," +
PropertyNames.SOURCE_OBJECT;
// 検索操作で使用される SearchSQL オブジェクトを構成
SearchSQL sql = new SearchSQL(sqlString + " FROM " + GuidConstants.Class_CheckinEvent +
" WHERE " + PropertyNames.DATE_CREATED + "> 20100401T080000Z" +
" ORDER BY " + PropertyNames.DATE_CREATED);
// 検索操作を実行
SearchScope ss = new SearchScope(store);
RepositoryRowSet rrc = ss.fetchRows(sql, null, null, null);
// 反復処理し、結果を出力
Iterator it = rrc.iterator();
while (it.hasNext())
{
RepositoryRow rr = (RepositoryRow) it.next();
// 記録された Event オブジェクトを取得し、その情報を出力
Id eventId = rr.getProperties().getIdValue(PropertyNames.ID);
Event eventObject = Factory.Event.fetchInstance(store, eventId, null);
String eventStatus = rr.getProperties().getInteger32Value(
PropertyNames.EVENT_STATUS).equals(new Integer(0)) ?
"Succeeded" : "Failed";
System.out.println("Event Properties:¥n" +
" Event ID: " + eventId.toString()+ "¥n" +
" Event Name: " + eventObject.getClassName()+ "¥n" +
" Date Created: " + rr.getProperties().getDateTimeValue(PropertyNames.DATE_CREATED)+ "¥n" +
" Event Status: " + eventStatus
);
// 変更されたソース・オブジェクトを取得し、オブジェクト名と最終更新日を出力
// 変更されたオブジェクトが記録されていない場合、null を返す
IndependentObject modifiedObject = (IndependentObject)rr.getProperties().getObjectValue(
PropertyNames.SOURCE_OBJECT);
if (modifiedObject!=null)
{
try {
System.out.println("Source modified object: " +
"¥n Name: " + modifiedObject.getProperties().getStringValue(PropertyNames.NAME) +
"¥n Date object modified: " + modifiedObject.getProperties().getDateTimeValue(
PropertyNames.DATE_LAST_MODIFIED) );
}
catch (EngineRuntimeException e)
{
System.out.println("Source modified object:¥n " + e.getMessage() );
}
}
else
{
// If the modified object was not recorded then neither was the original object.
System.out.println("There is no source modified or source original object recorded for this
audited event." + "¥n=================================¥n");
continue;
}
// 元のソース・オブジェクトを取得し、オブジェクト名と最終更新日を出力
// 元のオブジェクトが記録されていない場合、null を返す
IndependentObject originalObject = (IndependentObject) rr.getProperties().getObjectValue(
PropertyNames.ORIGINAL_OBJECT);
if (originalObject!=null)
{
try {
System.out.println("Source original object: " +
"¥n Name: " + originalObject.getProperties().getStringValue(PropertyNames.NAME) +
"¥n Date object modified: " + originalObject.getProperties().getDateTimeValue(
PropertyNames.DATE_LAST_MODIFIED) );
}
catch (EngineRuntimeException e)
{
System.out.println("Source original object: ¥n " + e.getMessage() );
}
System.out.println("¥n=================================¥n");
}
else
{
System.out.println("There is no source original object recorded for this audited event." +
"¥n=================================¥n");
}
}
C# の例
// SQL 選択ステートメントを作成する
String sqlString = "SELECT " + PropertyNames.ID + "," + PropertyNames.DATE_CREATED + "," +
PropertyNames.EVENT_STATUS + "," + PropertyNames.ORIGINAL_OBJECT + "," +
PropertyNames.SOURCE_OBJECT;
// 検索操作で使用される SearchSQL オブジェクトを構成
SearchSQL sql = new SearchSQL(sqlString + " FROM " + GuidConstants.Class_CheckinEvent +
" WHERE " + PropertyNames.DATE_CREATED + "> 20100401T080000Z" +
" ORDER BY " + PropertyNames.DATE_CREATED);
// 検索操作を実行
SearchScope ss = new SearchScope(store);
IRepositoryRowSet rrc = ss.FetchRows(sql, null, null, null);
// 反復処理し、結果を出力
foreach (IRepositoryRow rr in rrc)
{
IIndependentObject modifiedObject;
IEvent eventObject;
// 記録された Event オブジェクトを取得し、その情報を出力
Id eventId = rr.Properties.GetIdValue(PropertyNames.ID);
eventObject = Factory.Event.FetchInstance(store, eventId, null);
String eventStatus = rr.Properties.GetInteger32Value(PropertyNames.EVENT_STATUS) == 0 ?
"Succeeded" : "Failed";
System.Console.WriteLine("Event Properties:¥n" +
" Event ID: " + eventId.ToString() + "¥n" +
" Event Name: " + eventObject.GetClassName() + "¥n" +
" Date Created: " + rr.Properties.GetDateTimeValue(PropertyNames.DATE_CREATED)+ "¥n" +
" Event Status: " + eventStatus
);
// 変更されたソース・オブジェクトを取得し、オブジェクト名と最終更新日を出力
// 変更されたオブジェクトが記録されていない場合、null を返す
modifiedObject = (IIndependentObject)rr.Properties.GetObjectValue(PropertyNames.SOURCE_OBJECT);
if (modifiedObject!=null)
{
try {
System.Console.WriteLine("Source modified object: " +
"¥n Name: " + modifiedObject.Properties.GetStringValue(PropertyNames.NAME) +
"¥n Date object modified: " + modifiedObject.Properties.GetDateTimeValue(
PropertyNames.DATE_LAST_MODIFIED) );
}
catch (EngineRuntimeException e)
{
System.Console.WriteLine("Source modified object:¥n " + e.Message );
}
}
else
{
// If the modified object was not recorded then neither was the original object.
System.Console.WriteLine("There is no source modified or source original object recorded for
this audited event." + "¥n=================================¥n");
continue;
}
// 元のソース・オブジェクトを取得し、オブジェクト名と最終更新日を出力
// 元のオブジェクトが記録されていない場合、null を返す
IIndependentObject originalObject = (IIndependentObject)rr.Properties.GetObjectValue(
PropertyNames.ORIGINAL_OBJECT);
if (originalObject!=null)
{
try {
System.Console.WriteLine("Source original object: " +
"¥n Name: " + originalObject.Properties.GetStringValue(PropertyNames.NAME) +
"¥n Date object modified: " + originalObject.Properties.GetDateTimeValue(
PropertyNames.DATE_LAST_MODIFIED) );
}
catch (EngineRuntimeException e)
{
System.Console.WriteLine("Source original object: ¥n " + e.Message );
}
System.Console.WriteLine("¥n=================================¥n");
}
else
{
System.Console.WriteLine("There is no source original object recorded for this audited
event." + "¥n=================================¥n");
}
}