com.evolveum.midpoint.test.DummyAuditService.java Source code

Java tutorial

Introduction

Here is the source code for com.evolveum.midpoint.test.DummyAuditService.java

Source

/*
 * Copyright (c) 2010-2015 Evolveum
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.evolveum.midpoint.test;

import static org.testng.AssertJUnit.assertFalse;
import static org.testng.AssertJUnit.assertEquals;

import java.util.*;

import com.evolveum.midpoint.audit.api.AuditEventType;
import com.evolveum.midpoint.schema.result.OperationResult;

import net.sf.saxon.tree.wrapper.SiblingCountingNode;

import org.apache.commons.lang.StringUtils;

import com.evolveum.midpoint.audit.api.AuditEventRecord;
import com.evolveum.midpoint.audit.api.AuditEventStage;
import com.evolveum.midpoint.audit.api.AuditService;
import com.evolveum.midpoint.prism.Objectable;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismPropertyValue;
import com.evolveum.midpoint.prism.delta.ChangeType;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.prism.delta.PropertyDelta;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.util.PrismAsserts;
import com.evolveum.midpoint.schema.ObjectDeltaOperation;
import com.evolveum.midpoint.schema.result.OperationResultStatus;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.DebugDumpable;
import com.evolveum.midpoint.util.DebugUtil;
import com.evolveum.midpoint.xml.ns._public.common.common_3.CleanupPolicyType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType;

import org.apache.commons.lang.Validate;

import javax.xml.datatype.Duration;
import javax.xml.namespace.QName;

/**
 * Dummy audit service that only remembers the audit messages in runtime.
 * Only for use in tests.
 *  
 * @author semancik
 *
 */
public class DummyAuditService implements AuditService, DebugDumpable {

    private static DummyAuditService instance = null;

    private List<AuditEventRecord> records = new ArrayList<AuditEventRecord>();

    public static DummyAuditService getInstance() {
        if (instance == null) {
            instance = new DummyAuditService();
        }
        return instance;
    }

    @Override
    public void audit(AuditEventRecord record, Task task) {
        records.add(record.clone());
    }

    @Override
    public void cleanupAudit(CleanupPolicyType policy, OperationResult parentResult) {
        Validate.notNull(policy, "Cleanup policy must not be null.");
        Validate.notNull(parentResult, "Operation result must not be null.");

        if (policy.getMaxAge() == null) {
            return;
        }

        Duration duration = policy.getMaxAge();
        if (duration.getSign() > 0) {
            duration = duration.negate();
        }
        long minValue = duration.getTimeInMillis(new Date());

        Iterator<AuditEventRecord> iterator = records.iterator();
        while (iterator.hasNext()) {
            AuditEventRecord record = iterator.next();
            Long timestamp = record.getTimestamp();
            if (timestamp == null) {
                continue;
            }

            if (timestamp < minValue) {
                iterator.remove();
            }
        }
    }

    public List<AuditEventRecord> getRecords() {
        return records;
    }

    public void clear() {
        records.clear();
    }

    /**
     * Asserts that there is a request message followed by execution message.
     */
    public void assertSimpleRecordSanity() {
        Iterator<AuditEventRecord> iterator = records.iterator();
        int num = 0;
        int numRequests = 0;
        int numExecutions = 0;
        while (iterator.hasNext()) {
            AuditEventRecord record = iterator.next();
            num++;
            assertRecordSanity("" + num + "th record", record);

            if (record.getEventStage() == AuditEventStage.REQUEST) {
                numRequests++;
            }
            if (record.getEventStage() == AuditEventStage.EXECUTION) {
                assert numRequests > 0 : "Encountered execution stage audit record without any preceding request: "
                        + record;
                numExecutions++;
            }
        }
        assert numRequests <= numExecutions : "Strange number of requests and executions; " + numRequests
                + " requests, " + numExecutions + " executions";
    }

    private void assertRecordSanity(String recordDesc, AuditEventRecord record) {
        assert record != null : "Null audit record (" + recordDesc + ")";
        assert !StringUtils.isEmpty(record.getEventIdentifier()) : "No event identifier in audit record ("
                + recordDesc + ")";
        assert !StringUtils.isEmpty(record.getTaskIdentifier()) : "No task identifier in audit record ("
                + recordDesc + ")";
        // TODO
    }

    public void assertRecords(int expectedNumber) {
        assert records.size() == expectedNumber : "Unexpected number of audit records; expected " + expectedNumber
                + " but was " + records.size();
    }

    public List<AuditEventRecord> getRecordsOfType(AuditEventType type) {
        List<AuditEventRecord> retval = new ArrayList<AuditEventRecord>();
        for (AuditEventRecord record : records) {
            if (record.getEventType() == type) {
                retval.add(record);
            }
        }
        return retval;
    }

    public void assertRecords(AuditEventType type, int expectedNumber) {
        List<AuditEventRecord> filtered = getRecordsOfType(type);
        assert filtered.size() == expectedNumber : "Unexpected number of audit records of type " + type
                + "; expected " + expectedNumber + " but was " + filtered.size();
    }

    public AuditEventRecord getRequestRecord() {
        assertSingleBatch();
        AuditEventRecord requestRecord = records.get(0);
        assert requestRecord != null : "The first audit record is null";
        assert requestRecord
                .getEventStage() == AuditEventStage.REQUEST : "The first audit record is not request, it is "
                        + requestRecord;
        return requestRecord;
    }

    public AuditEventRecord getExecutionRecord(int index) {
        assertSingleBatch();
        AuditEventRecord executionRecord = records.get(index + 1);
        assert executionRecord != null : "The " + index + "th audit execution record is null";
        assert executionRecord.getEventStage() == AuditEventStage.EXECUTION : "The " + index
                + "th audit execution record is not execution, it is " + executionRecord;
        return executionRecord;
    }

    public List<AuditEventRecord> getExecutionRecords() {
        assertSingleBatch();
        return records.subList(1, records.size());
    }

    private void assertSingleBatch() {
        assert records.size() > 1 : "Expected at least two audit records but got " + records.size();
        Iterator<AuditEventRecord> iterator = records.iterator();
        AuditEventRecord requestRecord = iterator.next();
        if (requestRecord.getEventType() == AuditEventType.CREATE_SESSION) {
            requestRecord = iterator.next();
        }
        assert requestRecord
                .getEventStage() == AuditEventStage.REQUEST : "Expected first record to be request, it was "
                        + requestRecord.getEventStage() + " instead: " + requestRecord;
        while (iterator.hasNext()) {
            AuditEventRecord executionRecord = iterator.next();
            if (executionRecord.getEventType() == AuditEventType.TERMINATE_SESSION) {
                break;
            }
            assert executionRecord
                    .getEventStage() == AuditEventStage.EXECUTION : "Expected following record to be execution, it was "
                            + executionRecord.getEventStage() + " instead: " + executionRecord;
        }
    }

    public void assertAnyRequestDeltas() {
        AuditEventRecord requestRecord = getRequestRecord();
        Collection<ObjectDeltaOperation<? extends ObjectType>> requestDeltas = requestRecord.getDeltas();
        assert requestDeltas != null
                && !requestDeltas.isEmpty() : "Expected some deltas in audit request record but found none";
    }

    public Collection<ObjectDeltaOperation<? extends ObjectType>> getExecutionDeltas() {
        return getExecutionDeltas(0);
    }

    public Collection<ObjectDeltaOperation<? extends ObjectType>> getExecutionDeltas(int index) {
        AuditEventRecord executionRecord = getExecutionRecord(index);
        Collection<ObjectDeltaOperation<? extends ObjectType>> deltas = executionRecord.getDeltas();
        assert deltas != null : "Execution audit record has null deltas";
        return deltas;
    }

    public ObjectDeltaOperation<?> getExecutionDelta(int index) {
        Collection<ObjectDeltaOperation<? extends ObjectType>> deltas = getExecutionDeltas(index);
        assert deltas.size() == 1 : "Execution audit record has more than one deltas, it has " + deltas.size();
        ObjectDeltaOperation<?> delta = deltas.iterator().next();
        return delta;
    }

    public <O extends ObjectType> ObjectDeltaOperation<O> getExecutionDelta(int index, ChangeType changeType,
            Class<O> typeClass) {
        for (ObjectDeltaOperation<? extends ObjectType> deltaOp : getExecutionDeltas(index)) {
            ObjectDelta<? extends ObjectType> delta = deltaOp.getObjectDelta();
            if (delta.getObjectTypeClass() == typeClass && delta.getChangeType() == changeType) {
                return (ObjectDeltaOperation<O>) deltaOp;
            }
        }
        return null;
    }

    public void assertExecutionDeltaAdd() {
        ObjectDeltaOperation<?> delta = getExecutionDelta(0);
        assert delta.getObjectDelta().isAdd() : "Execution audit record is not add, it is " + delta;
    }

    public void assertExecutionSuccess() {
        assertExecutionOutcome(OperationResultStatus.SUCCESS);
    }

    public void assertExecutionOutcome(OperationResultStatus expectedStatus) {
        List<AuditEventRecord> executionRecords = getExecutionRecords();
        for (AuditEventRecord executionRecord : executionRecords) {
            assert executionRecord.getOutcome() == expectedStatus : "Expected execution outcome " + expectedStatus
                    + " in audit record but it was " + executionRecord.getOutcome();
        }
    }

    public void assertExecutionOutcome(int index, OperationResultStatus expectedStatus) {
        List<AuditEventRecord> executionRecords = getExecutionRecords();
        AuditEventRecord executionRecord = executionRecords.get(index);
        assert executionRecord.getOutcome() == expectedStatus : "Expected execution outcome " + expectedStatus
                + " in audit execution record (" + index + ") but it was " + executionRecord.getOutcome();
    }

    public void assertExecutionMessage() {
        List<AuditEventRecord> executionRecords = getExecutionRecords();
        for (AuditEventRecord executionRecord : executionRecords) {
            assert !StringUtils.isEmpty(executionRecord
                    .getMessage()) : "Expected execution message in audit record but there was none; in "
                            + executionRecord;
        }
    }

    public void assertExecutionMessage(int index) {
        List<AuditEventRecord> executionRecords = getExecutionRecords();
        AuditEventRecord executionRecord = executionRecords.get(index);
        assert !StringUtils.isEmpty(
                executionRecord.getMessage()) : "Expected execution message in audit record but there was none; in "
                        + executionRecord;
    }

    public void assertNoRecord() {
        assert records.isEmpty() : "Expected no audit record but some sneaked in: " + records;
    }

    public <O extends ObjectType> ObjectDeltaOperation<O> assertHasDelta(ChangeType expectedChangeType,
            Class<O> expectedClass) {
        return assertHasDelta(null, 0, expectedChangeType, expectedClass);
    }

    public <O extends ObjectType> ObjectDeltaOperation<O> assertHasDelta(ChangeType expectedChangeType,
            Class<O> expectedClass, OperationResultStatus expextedResult) {
        return assertHasDelta(null, 0, expectedChangeType, expectedClass, expextedResult);
    }

    public <O extends ObjectType> ObjectDeltaOperation<O> assertHasDelta(int index, ChangeType expectedChangeType,
            Class<O> expectedClass) {
        return assertHasDelta(null, index, expectedChangeType, expectedClass);
    }

    public <O extends ObjectType> ObjectDeltaOperation<O> assertHasDelta(int index, ChangeType expectedChangeType,
            Class<O> expectedClass, OperationResultStatus expextedResult) {
        return assertHasDelta(null, index, expectedChangeType, expectedClass, expextedResult);
    }

    public <O extends ObjectType> ObjectDeltaOperation<O> assertHasDelta(String message, int index,
            ChangeType expectedChangeType, Class<O> expectedClass) {
        return assertHasDelta(message, index, expectedChangeType, expectedClass, null);
    }

    public <O extends ObjectType> ObjectDeltaOperation<O> assertHasDelta(String message, int index,
            ChangeType expectedChangeType, Class<O> expectedClass, OperationResultStatus expextedResult) {
        ObjectDeltaOperation<O> deltaOp = getExecutionDelta(index, expectedChangeType, expectedClass);
        assert deltaOp != null : (message == null ? "" : message + ": ") + "Delta for " + expectedClass
                + " of type " + expectedChangeType + " was not found in audit trail";
        if (expextedResult != null) {
            assertEquals(
                    (message == null ? "" : message + ": ") + "Delta for " + expectedClass + " of type "
                            + expectedChangeType + " has unexpected result",
                    deltaOp.getExecutionResult().getStatus(), expextedResult);
        }
        return deltaOp;
    }

    public void assertExecutionDeltas(int expectedNumber) {
        assertExecutionDeltas(0, expectedNumber);
    }

    public void assertExecutionDeltas(int index, int expectedNumber) {
        assertEquals("Wrong number of execution deltas in audit trail (index " + index + ")", expectedNumber,
                getExecutionDeltas(index).size());
    }

    public void assertTarget(String expectedOid) {
        Collection<PrismObject<? extends ObjectType>> targets = new ArrayList<PrismObject<? extends ObjectType>>();
        for (AuditEventRecord record : records) {
            PrismObject<? extends ObjectType> target = record.getTarget();
            if (target != null && expectedOid.equals(target.getOid())) {
                return;
            }
            if (target != null) {
                targets.add(target);
            }
        }
        assert false : "Target " + expectedOid + " not found in audit records; found " + targets;
    }

    public <O extends ObjectType, T> void assertOldValue(ChangeType expectedChangeType, Class<O> expectedClass,
            QName attrName, T expectedValue) {
        assertOldValue(null, 0, expectedChangeType, expectedClass, new ItemPath(attrName), expectedValue);
    }

    public <O extends ObjectType, T> void assertOldValue(ChangeType expectedChangeType, Class<O> expectedClass,
            ItemPath propPath, T expectedValue) {
        assertOldValue(null, 0, expectedChangeType, expectedClass, propPath, expectedValue);
    }

    public <O extends ObjectType, T> void assertOldValue(int index, ChangeType expectedChangeType,
            Class<O> expectedClass, ItemPath propPath, T expectedValue) {
        assertOldValue(null, index, expectedChangeType, expectedClass, propPath, expectedValue);
    }

    public <O extends ObjectType, T> void assertOldValue(String message, int index, ChangeType expectedChangeType,
            Class<O> expectedClass, ItemPath propPath, T... expectedValues) {
        ObjectDeltaOperation<O> deltaOp = getExecutionDelta(index, expectedChangeType, expectedClass);
        assert deltaOp != null : (message == null ? "" : message + ": ") + "Delta for " + expectedClass
                + " of type " + expectedChangeType + " was not found in audit trail";
        PropertyDelta<Object> propDelta = deltaOp.getObjectDelta().findPropertyDelta(propPath);
        assert propDelta != null : "No property delta for " + propPath + " in Delta for " + expectedClass
                + " of type " + expectedChangeType;
        Collection<PrismPropertyValue<Object>> estimatedOldValues = propDelta.getEstimatedOldValues();
        assert estimatedOldValues != null && !estimatedOldValues.isEmpty() : "No old values in property delta for "
                + propPath + " in Delta for " + expectedClass + " of type " + expectedChangeType;
        PrismAsserts.assertValues(
                (message == null ? "" : message + ": ") + "Wrong old values in property delta for " + propPath
                        + " in Delta for " + expectedClass + " of type " + expectedChangeType,
                estimatedOldValues, expectedValues);
    }

    /**
     * Checks that the first record is login and the last is logout.
     */
    public void assertLoginLogout() {
        assertLoginLogout(null);
    }

    /**
     * Checks that the first record is login and the last is logout.
     */
    public void assertLoginLogout(String expectedChannel) {
        AuditEventRecord firstRecord = records.get(0);
        assertEquals("Wrong type of first audit record: " + firstRecord.getEventType(),
                AuditEventType.CREATE_SESSION, firstRecord.getEventType());
        assertEquals("Wrong outcome of first audit record: " + firstRecord.getOutcome(),
                OperationResultStatus.SUCCESS, firstRecord.getOutcome());
        AuditEventRecord lastRecord = records.get(records.size() - 1);
        assertEquals("Wrong type of last audit record: " + lastRecord.getEventType(),
                AuditEventType.TERMINATE_SESSION, lastRecord.getEventType());
        assertEquals("Wrong outcome of last audit record: " + lastRecord.getOutcome(),
                OperationResultStatus.SUCCESS, lastRecord.getOutcome());
        assertEquals("Audit session ID does not match", firstRecord.getSessionIdentifier(),
                lastRecord.getSessionIdentifier());
        assertFalse("Same login and logout event IDs",
                firstRecord.getEventIdentifier().equals(lastRecord.getEventIdentifier()));
        if (expectedChannel != null) {
            assertEquals("Wrong channel in first audit record", expectedChannel, firstRecord.getChannel());
            assertEquals("Wrong channel in last audit record", expectedChannel, lastRecord.getChannel());
        }
    }

    public void assertFailedLogin(String expectedChannel) {
        AuditEventRecord firstRecord = records.get(0);
        assertEquals("Wrong type of first audit record: " + firstRecord.getEventType(),
                AuditEventType.CREATE_SESSION, firstRecord.getEventType());
        assertEquals("Wrong outcome of first audit record: " + firstRecord.getOutcome(),
                OperationResultStatus.FATAL_ERROR, firstRecord.getOutcome());
        if (expectedChannel != null) {
            assertEquals("Wrong channel in first audit record", expectedChannel, firstRecord.getChannel());
        }
    }

    @Override
    public String toString() {
        return "DummyAuditService(" + records + ")";
    }

    @Override
    public String debugDump() {
        return debugDump(0);
    }

    @Override
    public String debugDump(int indent) {
        StringBuilder sb = new StringBuilder();
        DebugUtil.indentDebugDump(sb, indent);
        sb.append("DummyAuditService: ").append(records.size()).append(" records\n");
        DebugUtil.debugDump(sb, records, indent + 1, false);
        return sb.toString();
    }

    @Override
    public List<AuditEventRecord> listRecords(String query, Map<String, Object> params) {
        // TODO Auto-generated method stub
        return null;
    }

}