Package org.drools.guvnor.server

Source Code of org.drools.guvnor.server.TestScenarioServiceImplementation

/*
* Copyright 2012 JBoss Inc
*
* 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 org.drools.guvnor.server;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.inject.Inject;

import org.drools.ClockType;
import org.drools.RuleBase;
import org.drools.RuleBaseConfiguration;
import org.drools.RuleBaseFactory;
import org.drools.SessionConfiguration;
import org.drools.base.ClassTypeResolver;
import org.drools.common.InternalRuleBase;
import org.drools.common.InternalWorkingMemory;
import org.drools.core.util.BinaryRuleBaseLoader;
import org.drools.guvnor.client.common.AssetFormats;
import org.drools.guvnor.client.rpc.Asset;
import org.drools.guvnor.client.rpc.BuilderResult;
import org.drools.guvnor.client.rpc.BulkTestRunResult;
import org.drools.guvnor.client.rpc.DetailedSerializationException;
import org.drools.guvnor.client.rpc.ScenarioResultSummary;
import org.drools.guvnor.client.rpc.ScenarioRunResult;
import org.drools.guvnor.client.rpc.SingleScenarioResult;
import org.drools.guvnor.client.rpc.TestScenarioService;
import org.drools.guvnor.client.rpc.WorkItemService;
import org.drools.guvnor.server.builder.AuditLogReporter;
import org.drools.guvnor.server.builder.ClassLoaderBuilder;
import org.drools.guvnor.server.cache.RuleBaseCache;
import org.drools.guvnor.server.repository.Preferred;
import org.drools.guvnor.server.util.LoggingHelper;
import org.drools.ide.common.client.modeldriven.testing.Scenario;
import org.drools.ide.common.server.testscenarios.RuleCoverageListener;
import org.drools.ide.common.server.testscenarios.ScenarioRunner;
import org.drools.ide.common.shared.workitems.PortableWorkDefinition;
import org.drools.repository.AssetItem;
import org.drools.repository.AssetItemIterator;
import org.drools.repository.ModuleItem;
import org.drools.repository.RulesRepository;
import org.drools.rule.Package;
import org.drools.runtime.process.WorkItem;
import org.drools.runtime.process.WorkItemHandler;
import org.drools.runtime.process.WorkItemManager;
import org.drools.runtime.rule.ConsequenceException;
import org.drools.util.CompositeClassLoader;
import org.jboss.seam.remoting.annotations.WebRemote;
import org.jboss.seam.security.annotations.LoggedIn;

import com.google.gwt.user.client.rpc.SerializationException;

public class TestScenarioServiceImplementation
        implements TestScenarioService {


    private static final LoggingHelper log = LoggingHelper.getLogger(TestScenarioService.class);

    @Inject @Preferred
    private RulesRepository rulesRepository;

    @Inject
    private ServiceSecurity serviceSecurity;

    @Inject
    private RepositoryAssetOperations repositoryAssetOperations;

    @Inject
    private WorkItemService workItemService;

    @Inject
    private ServiceImplementation serviceImplementation;

    @Inject
    private RepositoryModuleOperations repositoryModuleOperations;

    @WebRemote
    @LoggedIn
    public SingleScenarioResult runScenario(String packageName,
                                            Scenario scenario) throws SerializationException {
        serviceSecurity.checkSecurityIsPackageDeveloperWithPackageName(packageName);

        return runScenario(packageName,
                scenario,
                null);
    }

    private SingleScenarioResult runScenario(
            String packageName,
            Scenario scenario,
            RuleCoverageListener coverage) throws SerializationException {
        try {
            return runScenario(
                    scenario,
                    this.rulesRepository.loadModule(packageName),
                    coverage);
        } catch (Exception e) {
            if (e instanceof DetailedSerializationException) {
                DetailedSerializationException exception = (DetailedSerializationException) e;
                if (exception.getErrs() != null) {
                    return new SingleScenarioResult(new ScenarioRunResult(exception.getErrs()));
                } else {
                    throw exception;
                }
            } else {
                throw new DetailedSerializationException("Unable to run the scenario.",
                        e.getMessage());
            }
        }
    }

    private SingleScenarioResult runScenario(Scenario scenario,
                                             ModuleItem item,
                                             RuleCoverageListener coverage) throws DetailedSerializationException {

        RuleBase ruleBase = loadCacheRuleBase(item);
        org.drools.rule.Package aPackage = ruleBase.getPackages()[0];

        SessionConfiguration sessionConfiguration = new SessionConfiguration();
        sessionConfiguration.setClockType(ClockType.PSEUDO_CLOCK);
        sessionConfiguration.setKeepReference(false);
        InternalWorkingMemory workingMemory = (InternalWorkingMemory) ruleBase.newStatefulSession(
                sessionConfiguration,
                null);

        if (coverage != null) {
            workingMemory.addEventListener(coverage);
        }

        //Add stub Work Item Handlers
        WorkItemHandler workItemHandlerStub = getWorkItemHandlerStub();
        for (PortableWorkDefinition portableWorkDefinition : workItemService.loadWorkItemDefinitions(item.getUUID())) {
            workingMemory.getWorkItemManager().registerWorkItemHandler(
                    portableWorkDefinition.getName(),
                    workItemHandlerStub);
        }

        //Run Test Scenario
        try {
            AuditLogReporter logger = new AuditLogReporter(workingMemory);
            CompositeClassLoader classLoader = ((InternalRuleBase) ruleBase).getRootClassLoader();
            new ScenarioRunner(
                    new ClassTypeResolver(
                            getAllImports(aPackage),
                            classLoader),
                    classLoader,
                    workingMemory
            ).run(scenario);

            return new SingleScenarioResult(
                    new ScenarioRunResult(scenario),
                    logger.buildReport());
        } catch (ClassNotFoundException e) {
            log.error("Unable to load a required class.",
                    e);
            throw new DetailedSerializationException("Unable to load a required class.",
                    e.getMessage());
        } catch (ConsequenceException e) {
            String messageShort = "There was an error executing the consequence of rule [" + e.getRule().getName() + "]";
            String messageLong = e.getMessage();
            if (e.getCause() != null) {
                messageLong += "\nCAUSED BY " + e.getCause().getMessage();
            }

            log.error(messageShort + ": " + messageLong,
                    e);
            throw new DetailedSerializationException(messageShort,
                    messageLong);
        } catch (Exception e) {
            log.error("Unable to run the scenario.",
                    e);
            throw new DetailedSerializationException("Unable to run the scenario.",
                    e.getMessage());
        }
    }


    private Set<String> getAllImports(Package aPackage) {
        Set<String> allImports = new HashSet<String>(aPackage.getImports().keySet());

        if (aPackage.getGlobals() != null) {
            for (Object o : aPackage.getGlobals().keySet()) {
                allImports.add(aPackage.getGlobals().get(o));
            }
        }
        // need this for Generated beans to work
        allImports.add(aPackage.getName() + ".*");
        return allImports;
    }

    /*
    * Set the Rule base in a cache
    */
    private RuleBase loadCacheRuleBase(ModuleItem packageItem) throws DetailedSerializationException {

        if (packageItem.isBinaryUpToDate() && RuleBaseCache.getInstance().contains(packageItem.getUUID())) {
            return RuleBaseCache.getInstance().get(packageItem.getUUID());
        } else {

            // we have to build the package, and try again.
            if (packageItem.isBinaryUpToDate()) {
                RuleBase ruleBase = loadRuleBase(packageItem);
                RuleBaseCache.getInstance().put(packageItem.getUUID(),
                        ruleBase);
                return ruleBase;
            } else {
                repositoryModuleOperations.buildModuleWithoutErrors(packageItem, false);
                RuleBase ruleBase = loadRuleBase(packageItem);
                RuleBaseCache.getInstance().put(packageItem.getUUID(),
                        ruleBase);
                return ruleBase;
            }

        }
    }

    public BulkTestRunResult runScenariosInPackage(ModuleItem packageItem) throws SerializationException {

        if (!packageItem.isBinaryUpToDate() || !RuleBaseCache.getInstance().contains(packageItem.getUUID())) {

            if (packageItem.isBinaryUpToDate()) {
                RuleBaseCache.getInstance().put(
                        packageItem.getUUID(),
                        loadRuleBase(packageItem));
            } else {
                BuilderResult result = repositoryModuleOperations.buildModule(packageItem,
                        false);
                if (result == null || result.getLines().size() == 0) {
                    RuleBaseCache.getInstance().put(
                            packageItem.getUUID(),
                            loadRuleBase(packageItem));
                } else {
                    return new BulkTestRunResult(
                            result,
                            null,
                            0,
                            null);
                }
            }
        }

        AssetItemIterator it = packageItem.listAssetsByFormat(AssetFormats.TEST_SCENARIO);
        List<ScenarioResultSummary> resultSummaries = new ArrayList<ScenarioResultSummary>();
        RuleBase rb = RuleBaseCache.getInstance().get(packageItem.getUUID());
        Package bin = rb.getPackages()[0];

        RuleCoverageListener coverage = new RuleCoverageListener(expectedRules(bin));

        while (it.hasNext()) {
            AssetItem as = it.next();
            if (!as.getDisabled()) {
                Asset asset = repositoryAssetOperations.loadAsset(as);
                Scenario sc = (Scenario) asset.getContent();
                runScenario(packageItem.getName(),
                        sc,
                        coverage);

                int[] totals = sc.countFailuresTotal();
                resultSummaries.add(new ScenarioResultSummary(totals[0],
                        totals[1],
                        asset.getName(),
                        asset.getDescription(),
                        asset.getUuid()));
            }
        }

        ScenarioResultSummary[] summaries = resultSummaries.toArray(new ScenarioResultSummary[resultSummaries.size()]);

        return new BulkTestRunResult(null,
                resultSummaries.toArray(summaries),
                coverage.getPercentCovered(),
                coverage.getUnfiredRules());

    }


    private HashSet<String> expectedRules(Package bin) {
        HashSet<String> h = new HashSet<String>();
        for (int i = 0; i < bin.getRules().length; i++) {
            h.add(bin.getRules()[i].getName());
        }
        return h;
    }

    //Creates a stub Work Item Handler that does nothing. A problem is that if the *real* Work Item Handler
    //sets a Result Parameter that is used in other rules the results of running the Test Scenario could (or
    //more likely would) be different than those expected. We can't use the *real* Work Item Handler as we
    //have no control what code it executes unless we look into using SecurityManagers...
    private WorkItemHandler getWorkItemHandlerStub() {
        return new WorkItemHandler() {

            public void executeWorkItem(WorkItem workItem,
                                        WorkItemManager manager) {
                //Does absolute nothing, however could log execution if needed
            }

            public void abortWorkItem(WorkItem workItem,
                                      WorkItemManager manager) {
            }

        };
    }

    private RuleBase loadRuleBase(ModuleItem item) throws DetailedSerializationException {
        try {
            return deserKnowledgebase(
                    item,
                    createClassLoaderBuilder(item).buildClassLoader());
        } catch (ClassNotFoundException e) {
            log.error("Unable to load rule base.",
                    e);
            throw new DetailedSerializationException("A required class was not found.",
                    e.getMessage());
        } catch (Exception e) {
            log.error("Unable to load rule base.",
                    e);
            log.info("...but trying to rebuild binaries...");
            try {
                BuilderResult builderResult = repositoryModuleOperations.buildModule(
                        item,
                        true);
                if (builderResult != null && builderResult.getLines().size() > 0) {
                    log.error("There were errors when rebuilding the knowledgebase.");
                    throw new DetailedSerializationException("There were errors when rebuilding the knowledgebase.",
                            "");
                }
            } catch (Exception e1) {
                log.error("Unable to rebuild the rulebase: " + e.getMessage());
                throw new DetailedSerializationException("Unable to rebuild the rulebase.",
                        e.getMessage());
            }
            try {
                return deserKnowledgebase(
                        item,
                        createClassLoaderBuilder(item).buildClassLoader());
            } catch (Exception e2) {
                log.error("Unable to reload knowledgebase: " + e.getMessage());
                throw new DetailedSerializationException("Unable to reload knowledgebase.",
                        e.getMessage());
            }

        }
    }

    private ClassLoaderBuilder createClassLoaderBuilder(ModuleItem packageItem) {
        return new ClassLoaderBuilder(packageItem.listAssetsWithVersionsSpecifiedByDependenciesByFormat(AssetFormats.MODEL));
    }

    private RuleBase deserKnowledgebase(ModuleItem item,
                                        ClassLoader classloader) throws IOException,
                                                                ClassNotFoundException {
        RuleBase rulebase = RuleBaseFactory.newRuleBase( new RuleBaseConfiguration( classloader ) );
        BinaryRuleBaseLoader rbl = new BinaryRuleBaseLoader( rulebase,
                                                             classloader );
        rbl.addPackage( new ByteArrayInputStream( item.getCompiledBinaryBytes() ) );
        return rulebase;
    }

    @WebRemote
    @LoggedIn
    public BulkTestRunResult runScenariosInPackage(String packageUUID) throws SerializationException {
        serviceSecurity.checkSecurityIsPackageDeveloperWithPackageUuid(packageUUID);
        ModuleItem item = rulesRepository.loadModuleByUUID(packageUUID);
        return runScenariosInPackage(item);
    }


}
TOP

Related Classes of org.drools.guvnor.server.TestScenarioServiceImplementation

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.