org.apache.openaz.xacml.pdp.test.policy.TestPolicy.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.openaz.xacml.pdp.test.policy.TestPolicy.java

Source

/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you 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 org.apache.openaz.xacml.pdp.test.policy;

import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Marshaller;

import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributesType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObjectFactory;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicySetType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.RequestType;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.ParseException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.openaz.xacml.api.AttributeValue;
import org.apache.openaz.xacml.api.DataType;
import org.apache.openaz.xacml.api.DataTypeException;
import org.apache.openaz.xacml.api.DataTypeFactory;
import org.apache.openaz.xacml.api.Identifier;
import org.apache.openaz.xacml.api.XACML3;
import org.apache.openaz.xacml.pdp.test.TestBase;
import org.apache.openaz.xacml.std.IdentifierImpl;
import org.apache.openaz.xacml.util.FactoryException;
import org.apache.openaz.xacml.util.XACMLObjectCopy;
import org.apache.openaz.xacml.util.XACMLPolicyAggregator;
import org.apache.openaz.xacml.util.XACMLPolicyScanner;
import org.apache.openaz.xacml.util.XACMLProperties;

/**
 * This class reads the policy in and extracts all the attributes and their values that is contained in the
 * Policy. It then generates a request every single combination of attributes found. The attributes mostly
 * come from the Target Match elements, since they have both an attribute designator/selector matched with an
 * attribute value.
 */
public class TestPolicy extends TestBase {
    private static Log logger = LogFactory.getLog(TestPolicy.class);

    private boolean skip;
    private Path policy;
    private XACMLPolicyAggregator aggregator = new XACMLPolicyAggregator();
    private long index;

    //
    // Our command line parameters
    //
    public static final String OPTION_POLICY = "policy";
    public static final String OPTION_SKIP_GENERATE = "skip";

    static {
        options.addOption(new Option(OPTION_POLICY, true, "Path to the policy file."));
        options.addOption(new Option(OPTION_SKIP_GENERATE, false, "Skip generating requests."));
    }

    public class FlattenerObject {
        Identifier category;
        Identifier datatype;
        Identifier attribute;
        Set<AttributeValue<?>> values;
    }

    /**
     * This application exercises a policy by producing ALL the possible request combinations for a policy.
     * -policy Path to a policy file
     *
     * @param args
     * @throws HelpException
     * @throws org.apache.commons.cli.ParseException
     * @throws java.net.MalformedURLException
     */

    public TestPolicy(String[] args) throws MalformedURLException, ParseException, HelpException {
        super(args);
    }

    /*
     * Look for the -policy command line argument. This application needs a pointer to a specific policy in
     * order to run. (non-Javadoc)
     * @see org.apache.openaz.xacml.pdp.test.TestBase#parseCommands(java.lang.String[])
     */
    @Override
    protected void parseCommands(String[] args) throws ParseException, MalformedURLException, HelpException {
        //
        // Have our super do its job
        //
        super.parseCommands(args);
        //
        // Look for the policy option
        //
        CommandLine cl = new DefaultParser().parse(options, args);
        if (cl.hasOption(OPTION_POLICY)) {
            this.policy = Paths.get(cl.getOptionValue(OPTION_POLICY));
            //
            // Ensure it exists
            //
            if (Files.notExists(this.policy)) {
                throw new ParseException("Policy file does not exist.");
            }
        } else {
            throw new ParseException("You need to specify the policy file to be used.");
        }
        if (cl.hasOption(OPTION_SKIP_GENERATE)) {
            this.skip = true;
        } else {
            this.skip = false;
        }
    }

    /*
     * We override this method because here is where we want to scan the policy and aggregate all the
     * attributes that are defined within the policy. This routine will then dump all the possible requests
     * into the requests sub-directory. Thus, when this method returns the TestBase can proceed to iterate
     * each generated request and run it against the PDP engine. (non-Javadoc)
     * @see org.apache.openaz.xacml.pdp.test.TestBase#configure()
     */
    @Override
    protected void configure() throws FactoryException {
        //
        // Have our base class do its thing
        //
        super.configure();
        //
        // Setup where the PDP can find the policy
        //
        System.setProperty(XACMLProperties.PROP_ROOTPOLICIES, "policy");
        System.setProperty("policy.file", this.policy.toString());
        //
        // Determine if they want us to skip generation. This helps when a huge number of
        // requests will get generated for a policy and can take some time to do so. The user
        // can generate the requests once and then start testing a policy against the requests. Thus,
        // the attributes never changed but the policy logic did (saves time).
        //
        if (this.skip) {
            return;
        }
        //
        // Now we will scan the policy and get all the attributes.
        //
        XACMLPolicyScanner scanner = new XACMLPolicyScanner(this.policy, this.aggregator);
        //
        // The scanner returns us a policy object
        //
        Object policyObject = scanner.scan();
        //
        // Just dump some info
        //
        if (policyObject instanceof PolicySetType) {
            logger.info("Creating requests for policyset: " + ((PolicySetType) policyObject).getDescription());
        } else if (policyObject instanceof PolicyType) {
            logger.info("Creating requests for policy: " + ((PolicyType) policyObject).getDescription());
        }
        //
        // Call the function to create the requests
        //
        if (policyObject != null) {
            this.createRequests();
        }

        logger.info("Completed Generating requests.");
    }

    @SuppressWarnings("unchecked")
    protected void createRequests() {
        //
        // Clear out our request directory
        //
        this.removeRequests();
        //
        // Get our map
        //
        Map<Identifier, Map<Identifier, Map<Identifier, Set<AttributeValue<?>>>>> attributeMap = this.aggregator
                .getAttributeMap();
        //
        // We're going to create an initial flat list of requests for each unique attribute ID. Unique being
        // the
        // category, datatype and attribute id.
        //
        // By flattening the list, it makes it easier to then generate all the combinations of possible
        // requests.
        //
        List<FlattenerObject> attributes = new ArrayList<FlattenerObject>();
        //
        // Iterate through all the maps, we are going to flatten it
        // out into an array list.
        //
        for (Map.Entry<Identifier, Map<Identifier, Map<Identifier, Set<AttributeValue<?>>>>> categoryEntry : attributeMap
                .entrySet()) {
            String category = categoryEntry.getKey().toString();
            if (logger.isDebugEnabled()) {
                logger.debug("Category: " + category);
            }
            Map<Identifier, Map<Identifier, Set<AttributeValue<?>>>> datatypeMap = categoryEntry.getValue();
            for (Map.Entry<Identifier, Map<Identifier, Set<AttributeValue<?>>>> datatypeEntry : datatypeMap
                    .entrySet()) {
                String datatype = datatypeEntry.getKey().toString();
                if (logger.isDebugEnabled()) {
                    logger.debug("\tData Type: " + datatype);
                }
                Map<Identifier, Set<AttributeValue<?>>> attributeIDMap = datatypeEntry.getValue();
                for (Map.Entry<Identifier, Set<AttributeValue<?>>> attributeIDEntry : attributeIDMap.entrySet()) {
                    String attributeID = attributeIDEntry.getKey().toString();
                    if (logger.isDebugEnabled()) {
                        logger.debug("\t\tAttribute ID: " + attributeID);
                    }
                    Set<AttributeValue<?>> attributeValueSet = attributeIDEntry.getValue();
                    //
                    // Sanity check to see if there are any values. Sometimes there isn't if an attribute
                    // is a designator that is part of a condition or variable.
                    //
                    if (attributeValueSet.isEmpty()) {
                        if (logger.isDebugEnabled()) {
                            logger.debug("No values for attribute " + attributeIDEntry.getKey().stringValue());
                        }
                        //
                        // Check for the boolean datatype, in that case we can safely
                        // assume the true/false are ALL the possible values.
                        //
                        if (!datatypeEntry.getKey().equals(XACML3.ID_DATATYPE_BOOLEAN)) {
                            //
                            // Not boolean, so skip it
                            //
                            continue;
                        }
                        if (logger.isDebugEnabled()) {
                            logger.debug("No values but its a boolean datatype, we will include it anyway.");
                        }
                    }
                    //
                    // Create our flattener object
                    //
                    FlattenerObject flat = new FlattenerObject();
                    flat.category = categoryEntry.getKey();
                    flat.datatype = datatypeEntry.getKey();
                    flat.attribute = attributeIDEntry.getKey();
                    flat.values = new HashSet<AttributeValue<?>>();
                    if (datatypeEntry.getKey().equals(XACML3.ID_DATATYPE_BOOLEAN)) {
                        //
                        // There are only 2 possible values, true or false
                        //
                        flat.values.add(this.createAttributeValue(flat.datatype, true));
                        flat.values.add(this.createAttributeValue(flat.datatype, false));
                    } else {
                        flat.values.addAll(attributeValueSet);
                    }
                    attributes.add(flat);
                }
            }
        }
        if (attributes.size() <= 1) {
            //
            // Only one attribute, why bother
            //
            logger.info("Not enough attributes in policy: " + attributes.size());
            return;
        }
        /*
         * PLD work more on this later. This combinatorial formula is only accurate if each attribute has one
         * value.
         */
        if (logger.isDebugEnabled()) {
            //
            // This isn't really accurate, if an attribute has more than one value
            //
            logger.debug(attributes.size() + " will generate " + computePossibleCombinations(attributes.size()));
        }
        this.index = 1;
        for (int i = 0; i < attributes.size(); i++) {
            FlattenerObject flat = attributes.get(i);
            for (AttributeValue<?> value : flat.values) {
                //
                // Create a basic request object for just that attribute value.
                //
                RequestType request = new RequestType();
                //
                AttributesType attrs = new AttributesType();
                attrs.setCategory(flat.category.stringValue());
                request.getAttributes().add(attrs);
                //
                AttributeType attr = new AttributeType();
                attr.setAttributeId(flat.attribute.stringValue());
                attrs.getAttribute().add(attr);
                //
                AttributeValueType val = new AttributeValueType();
                val.setDataType(flat.datatype.stringValue());
                if (value.getValue() instanceof Collection) {
                    val.getContent().addAll((Collection<? extends Object>) value.getValue());
                } else {
                    val.getContent().add(value.getValue().toString());
                }
                //
                attr.getAttributeValue().add(val);
                //
                // Dump it out
                //
                this.writeRequest(request);
                //
                // Initiate recursive call to add other attributes to the request
                //
                this.recursivelyGenerateRequests(request, i + 1, attributes);
            }
        }
    }

    protected void recursivelyGenerateRequests(RequestType request, int i, List<FlattenerObject> attributes) {
        if (logger.isTraceEnabled()) {
            logger.trace("recursiveGenerate index: " + index + " i: " + i);
        }
        for (; i < attributes.size(); i++) {
            FlattenerObject flat = attributes.get(i);
            for (AttributeValue<?> value : flat.values) {
                //
                // Make a copy of the request
                //
                RequestType copyRequest = XACMLObjectCopy.deepCopy(request);
                //
                // Create the value object
                //
                AttributeValueType newValue = new AttributeValueType();
                newValue.setDataType(flat.datatype.stringValue());
                if (value.getValue() instanceof Collection) {
                    for (Object v : (Collection<?>) value.getValue()) {
                        newValue.getContent().add(v.toString());
                    }
                } else {
                    newValue.getContent().add(value.getValue().toString());
                }
                //
                // Add the value to the request
                //
                this.addAttribute(copyRequest, flat.category.stringValue(), flat.attribute.stringValue(), newValue);
                //
                // Now write it out
                //
                this.writeRequest(copyRequest);
                //
                // Recursively go through the rest of the attributes
                //
                this.recursivelyGenerateRequests(copyRequest, i + 1, attributes);
            }
        }
    }

    public static long computePossibleCombinations(long numberOfAttributes) {
        long num = 0;
        for (long i = numberOfAttributes; i > 0; i--) {
            num += computeCombinations(numberOfAttributes, i);
        }
        return num;
    }

    public static long computeFactorial(long n) {
        long fact = 1;
        for (long i = 1; i <= n; i++) {
            fact *= i;
        }
        return fact;
    }

    public static long computePermutationsWithoutRepetition(long n, long r) {
        //
        // n!
        // ---------
        // (n - r)!
        //
        long nPrime = 1;
        long n_rPrime = 1;
        for (long i = n; i > 1; i--) {
            nPrime *= i;
        }

        for (long i = (n - r); i > 1; i--) {
            n_rPrime *= i;
        }
        return nPrime / n_rPrime;
    }

    public static long computeCombinations(long n, long r) {
        //
        // n!
        // -----------
        // r! * (n-r)!
        //
        long nPrime = 1;
        long rPrime = 1;
        long n_rPrime = 1;

        for (long i = n; i > 1; i--) {
            nPrime *= i;
        }

        for (long i = r; i > 1; i--) {
            rPrime *= i;
        }

        for (long i = (n - r); i > 1; i--) {
            n_rPrime *= i;
        }

        return nPrime / (rPrime * n_rPrime);
    }

    protected Set<AttributeValue<?>> getAttributeValues(RequestType request) {
        //
        // Get our map
        //
        Map<Identifier, Map<Identifier, Map<Identifier, Set<AttributeValue<?>>>>> attributeMap = this.aggregator
                .getAttributeMap();
        //
        // Find the attribute
        //
        AttributesType attrs = request.getAttributes().get(0);
        Map<Identifier, Map<Identifier, Set<AttributeValue<?>>>> categoryMap = attributeMap
                .get(new IdentifierImpl(attrs.getCategory()));
        if (categoryMap != null) {
            AttributeType a = attrs.getAttribute().get(0);
            Map<Identifier, Set<AttributeValue<?>>> datatypeMap = categoryMap
                    .get(new IdentifierImpl(a.getAttributeValue().get(0).getDataType()));
            if (datatypeMap != null) {
                Set<AttributeValue<?>> values = datatypeMap.get(new IdentifierImpl(a.getAttributeId()));
                if (values != null) {
                    return values;
                }
            }
        }
        return Collections.emptySet();
    }

    protected AttributeValue<?> createAttributeValue(Identifier datatype, Object value) {
        DataTypeFactory dataTypeFactory = null;
        try {
            dataTypeFactory = DataTypeFactory.newInstance();
            if (dataTypeFactory == null) {
                logger.error("Could not create data type factory");
                return null;
            }
        } catch (FactoryException e) {
            logger.error("Can't get Data type Factory: " + e.getLocalizedMessage());
            return null;
        }
        DataType<?> dataTypeExtended = dataTypeFactory.getDataType(datatype);
        if (dataTypeExtended == null) {
            logger.error("Unknown datatype: " + datatype);
            return null;
        }
        try {
            return dataTypeExtended.createAttributeValue(value);
        } catch (DataTypeException e) {
            logger.error(e);
        }
        return null;
    }

    protected void removeRequests() {
        //
        // Delete any existing request files that we generate. i.e. Have the Unknown in the file name.
        //
        try {
            Files.walkFileTree(Paths.get(this.directory.toString(), "requests"), new SimpleFileVisitor<Path>() {

                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    //
                    // Sanity check the file name
                    //
                    Matcher matcher = pattern.matcher(file.getFileName().toString());
                    if (matcher.matches()) {
                        try {
                            //
                            // Pull what this request is supposed to be
                            //
                            String group = null;
                            int count = matcher.groupCount();
                            if (count >= 1) {
                                group = matcher.group(count - 1);
                            }
                            //
                            // Send it
                            //
                            if (group.equals("Unknown")) {
                                //
                                // Remove the file
                                //
                                Files.delete(file);
                            }
                        } catch (Exception e) {
                            logger.error(e);
                            e.printStackTrace();
                        }
                    }
                    return super.visitFile(file, attrs);
                }
            });
        } catch (IOException e) {
            logger.error("Failed to removeRequests from " + this.directory + " " + e);
        }
    }

    protected void addRequests(RequestType request, List<RequestType> requests, int index) {
        for (RequestType req : requests) {
            //
            // There really should only be one attribute
            //
            for (AttributesType attrs : req.getAttributes()) {
                for (AttributeType attr : attrs.getAttribute()) {
                    for (AttributeValueType value : attr.getAttributeValue()) {
                        if (this.addAttribute(request, attrs.getCategory(), attr.getAttributeId(), value)) {
                            this.writeRequest(request);
                        }
                    }
                }
            }
        }
    }

    /**
     * Writes the request into the "requests" sub-directory, relative to the value of the "directory" setup
     * during initialization. Writing the requests out allows one to go back and easily refer to the request
     * when analyzing the responses generated after the PDP decide() call. Also, one can then use the
     * generated requests into any test tools they wish to build.
     *
     * @param request - The request to be written.
     */
    protected void writeRequest(RequestType request) {
        if (logger.isTraceEnabled()) {
            logger.trace("writeRequest: " + index);
        }
        try {
            ObjectFactory of = new ObjectFactory();
            JAXBElement<RequestType> requestElement = of.createRequest(request);
            JAXBContext context = JAXBContext.newInstance(RequestType.class);
            Marshaller m = context.createMarshaller();
            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
            Path outFile = Paths.get(this.directory, "requests",
                    String.format("Request.%06d.Unknown.xml", this.index));
            m.marshal(requestElement, outFile.toFile());
        } catch (Exception e) {
            logger.error("Failed to write request: " + e.getMessage());
        }
        this.index++;
    }

    protected boolean addAttribute(RequestType request, String category, String id, AttributeValueType value) {
        //
        // See if the category exists
        //
        for (AttributesType attrs : request.getAttributes()) {
            if (attrs.getCategory().equals(category)) {
                //
                // It does have the category. But does it have the attribute ID?
                //
                for (AttributeType attr : attrs.getAttribute()) {
                    if (attr.getAttributeId().equals(id)) {
                        //
                        // Yes, check for the same datatype
                        //
                        for (AttributeValueType val : attr.getAttributeValue()) {
                            if (val.getDataType().equals(value.getDataType())) {
                                //
                                // We have something already there
                                //
                                return false;
                            }
                        }
                        //
                        // The ID exists, but not the datatype
                        //
                        attr.getAttributeValue().add(value);
                        return true;
                    }
                }
                //
                // If we get here, the ID does not exist
                //
                AttributeType attr = new AttributeType();
                attr.setAttributeId(id);
                attr.getAttributeValue().add(value);
                attrs.getAttribute().add(attr);
                return true;
            }
        }
        //
        // If we get here, the category does not exist. So add it in.
        //
        AttributesType attrs = new AttributesType();
        attrs.setCategory(category);
        AttributeType attr = new AttributeType();
        attr.setAttributeId(id);
        attr.getAttributeValue().add(value);
        attrs.getAttribute().add(attr);
        request.getAttributes().add(attrs);
        return true;
    }

    public static void main(String[] args) {
        try {
            new TestPolicy(args).run();
        } catch (ParseException | IOException | FactoryException e) {
            logger.error(e);
        } catch (HelpException e) {
        }
    }

    /*
     * // Map<CATEGORY, MAP<DATATYPE, MAP<ATTRIBUTEID, SET<VALUES>>>
     * @SuppressWarnings("unchecked") private void generateRequests(Map<Identifier, Map<Identifier,
     * Map<Identifier, Set<AttributeValue<?>>>>> categoryMap) { meta = new ArrayList<>(); for
     * (Map.Entry<Identifier, Map<Identifier, Map<Identifier, Set<AttributeValue<?>>>>> categoryEntry :
     * categoryMap.entrySet()) { String category = categoryEntry.getKey().toString();
     * logger.debug("Category: " + category); Map<Identifier, Map<Identifier, Set<AttributeValue<?>>>>
     * datatypeMap = categoryEntry.getValue(); for (Map.Entry<Identifier, Map<Identifier,
     * Set<AttributeValue<?>>>> datatypeEntry : datatypeMap.entrySet()) { String datatype =
     * datatypeEntry.getKey().toString(); logger.debug("\tData Type: " + datatype); Map<Identifier,
     * Set<AttributeValue<?>>> attributeIDMap = datatypeEntry.getValue(); for (Map.Entry<Identifier,
     * Set<AttributeValue<?>>> attributeIDEntry : attributeIDMap.entrySet()) { String attributeID =
     * attributeIDEntry.getKey().toString(); logger.debug("\t\tAttribute ID: " + attributeID);
     * Set<AttributeValue<?>> attributeValueSet = attributeIDEntry.getValue(); for (AttributeValue<?> value :
     * attributeValueSet) { logger.debug("\t\t\tAttribute Value: " + value); } Iterator<AttributeValue<?>>
     * iterator = attributeValueSet.iterator(); logger.debug("\t\t\t# of Attribute values: " +
     * attributeValueSet.size()); meta.add(new Object[] {category, datatype, attributeID, iterator.next(),
     * iterator, attributeValueSet}); } } } int count = 0; for (File file : output.toFile().listFiles()) {
     * file.delete(); } do { RequestType request = new RequestType(); request.setCombinedDecision(false);
     * request.setReturnPolicyIdList(false); List<AttributesType> attributesList = request.getAttributes();
     * Map<String, AttributesType> category2Attribute= new HashMap<>(); for (int i = 0; i < meta.size(); i++)
     * { Object[] record = meta.get(i); AttributesType attributes = null; if
     * (category2Attribute.containsKey(record[0].toString())) attributes =
     * category2Attribute.get(record[0].toString()); else { attributes = new AttributesType();
     * attributes.setCategory(record[0].toString()); category2Attribute.put(record[0].toString(), attributes);
     * attributesList.add(attributes); } // attributes.setId(record[2].toString()); List<AttributeType>
     * attrList = attributes.getAttribute(); AttributeType attribute = new AttributeType();
     * attribute.setAttributeId(record[2].toString()); List<AttributeValueType> valueList =
     * attribute.getAttributeValue(); AttributeValue<?> attributeValue = (AttributeValue<?>) record[3];
     * AttributeValueType value = new AttributeValueType();
     * value.setDataType(attributeValue.getDataTypeId().toString()); List<Object> content =
     * value.getContent(); content.addAll((Collection<? extends Object>) attributeValue.getValue());
     * valueList.add(value); attrList.add(attribute); } try { ObjectFactory of = new ObjectFactory();
     * JAXBElement<RequestType> requestElement = of.createRequest(request); JAXBContext context =
     * JAXBContext.newInstance(RequestType.class); Marshaller m = context.createMarshaller();
     * m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); m.marshal(requestElement,
     * output.resolve("request" + count + ".xml").toFile()); // if (count == 0) {//Just send the first request
     * to the engine StringWriter sw = new StringWriter(); m.marshal(requestElement, sw);
     * logger.info(sw.toString()); EngineCaller engine = new LocalEngineCaller(); if (engine.startEngine(""))
     * { String response = engine.decide(sw.toString(), "xml"); FileWriter writer = new
     * FileWriter(output.resolve("response" + count + ".xml").toFile()); writer.write(response);
     * writer.close(); logger.info("Response received: \n" + response); } // } } catch (Exception e) {
     * e.printStackTrace(); } count++; } while (hasNextRequest()); logger.info("# of requests generated: " +
     * count); } private boolean hasNextRequest() { int i = meta.size() - 1; Object[] record = meta.get(i);
     * @SuppressWarnings("unchecked") Iterator<AttributeValue<?>> iterator = (Iterator<AttributeValue<?>>)
     * record[4]; if (iterator.hasNext()) { record[3] = iterator.next(); } else { return
     * recycleAttributeValue(i); } return true; }
     * @SuppressWarnings("unchecked") private boolean recycleAttributeValue(int position) { boolean rc = true;
     * if (position == 0) return false; Object[] record = meta.get(position); Set<AttributeValue<?>>
     * attributeValueSet = (Set<AttributeValue<?>>) record[5]; Iterator<AttributeValue<?>> newIt =
     * attributeValueSet.iterator(); record[4] = newIt; record[3] = newIt.next(); int i = position - 1;
     * Object[] previous = meta.get(i); Iterator<AttributeValue<?>> preIt = (Iterator<AttributeValue<?>>)
     * previous[4]; if (preIt.hasNext()) { previous[3] = preIt.next(); } else { rc = recycleAttributeValue(i);
     * } return rc; }
     */

}