Chapter 11. Filters

Table of Contents

11.1. Create a Filter

In real systems, messages may be modified before they are sent, e.g. they may be signed or encrypted, messages have to be transformed to other formats, because the real system can not handle XML messages but has its own message format. In the tutorial example, client messages can be protected from changes by a calculated checksum. Of course, this simple modification could be handled by a plug-in and a substitution or composition in a template, other manipulations like encrypting are more complex and can not be handled with plug-ins. This manipulation often should be performed without being explicitly noted in the test case, because the manipulation is not in the scope of the tests. Therefore, PETA offers the extension mechanism of filters to manipulate messages. A filter gets a message as input and transforms this message to output. It is realized as a java class that implements the de.verit.peta.engine.filter.Filter interface. A filter may be explicitly called in the test case, which will be done in the tutorial example or they may be referenced in the PETA configuration and implicitly used for all operations of the related actors.

[Note]Further information

Detailed information about PETA filters can be found in the PETA-Core Reference Manual.

11.1. Create a Filter

To create a new filter, press the New filter button in the toolbar. In the wizard, set the source folder of the filter's java file to TutorialProject/src and enter a package name. Enter Checksum as the class name and press the Next button. On the second page, enter a description for this filter. As the filter does not need an argument, press the Finish button to create a java file in the specified package and open it in the editor.

Figure 11.1.  Create new PETA filter

Create new PETA filter


The following code example shows the implementation of the Checksum filter. If an outgoing message does not have a checksum, the filter adds a calculated checksum to it. Otherwise, the message is not changed. While acting as an input filter, the checksum is extracted and removed from the incoming message and validated against a calculated checksum. In case of a mismatch, the context value _peta/filterChecksum_Result is set to failed , otherwise, the context value is set to ok.

Context values starting with _peta/ are special read only context values which will not be checked during the test case validation (validation of references to context values). Therefore, references to such a context value can be used in test cases without the need to define the context value. To set the value of such a context value in a filter, the method setForced has to be used instead of the method set, otherwise, the test case using the filter would fail.

Example 11.1.  Implementation of the Checksum filter

package de.verit.peta.tutorial.filter;

import java.util.zip.CRC32;
import de.verit.peta.common.PetaErrorException;
import de.verit.peta.engine.context.Constants;
import de.verit.peta.engine.context.ContextCache;
import de.verit.peta.engine.document.Message;
import de.verit.peta.engine.filter.Filter;
import de.verit.peta.engine.filter.FilterBase;

public class Checksum extends FilterBase implements Filter {

    /**
     * @see Filter#filter(de.verit.peta.engine.document.Message,
     *                de.verit.peta.engine.context.ContextCache)
     */
    public Message filter(Message inputMessage,
                          ContextCache context)
        throws PetaErrorException {

        Message filteredMessage = null;
        final String me = context.get(Constants.ACTOR);
        final String sender = context.get(Constants.SENDER);
        if (me.equals(sender)) {
            // sending the message

            // insert checksum into message
            long checksum = getChecksum(inputMessage);
            String messageString = inputMessage.getAsString();
            messageString =
                messageString.replaceAll("(<request *)>", "$1"
                    + " checksum=\"" + checksum + "\">");
            filteredMessage = new Message(messageString);
        } else {
            // receiving the message

            // extract checksum from message
            String messageString = inputMessage.getAsString();
            long receivedChecksum = Long.parseLong(
                messageString.replaceAll("\n", "").replaceAll(
                    "<request.*? checksum=\"(.*)\".*", "$1"));

            // remove checksum from message
            messageString = messageString.replaceAll(
                    "(<request.*?) checksum=\".*\">",
                    "$1>");
            filteredMessage = new Message(messageString);

            // validate checksum
            long calculatedChecksum = getChecksum(filteredMessage);
            if (calculatedChecksum == receivedChecksum) {
                context.setForced("_peta/filterChecksum_Result",
                                  "ok");
            } else {
                context.setForced("_peta/filterChecksum_Result",
                                  "failed");
            }
        }
        return filteredMessage;
    }

    /**
     * Get checksum for given message.
     *
     * @param message The message.
     * @return The message's checksum.
     */
    private long getChecksum(final Message message) {
        CRC32 crc32 = new CRC32();
        crc32.update(message.getAsBinary());
        return crc32.getValue();
    }
}

Now the new filter can be used in the test cases. In this example, it will be used when the client sends the message to the server. Therefore, the filter has to be added as the output filter of the client's operation and as the input filter of the server's check request event.

To add the output filter, drag'n'drop the Add Outputfilter symbol to the first operation. In the wizard, select Checksum from the list of available filters and press the OK button.

Figure 11.2. Add the outputfilter

Add the outputfilter


To add the input filter, the module checkRequest has to be opened in a PETA editor. Expand its event and drag'n'drop the Add Inputfilter symbol to this event. In the wizard, select Checksum from the list of available filters and press the OK button.

To assert the successful checksum validation, drag'n'drop the Add Assertion symbol from the palette to a place in the event above the existing assertions. Add checksum validation ok as the name of the assertion, set the operator to == and the data type to String. As a context value (set by the filter) shall be asserted, press the left Add Reference button and enter the key _peta/filterChecksum_Result. Then, press the right Add Constant button and enter the expected constant value ok. Finish adding the new assertion by pressing the OK button.