Package org.drools.guvnor.server

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

/*
* Copyright 2011 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.Iterator;
import java.util.List;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.inject.Named;

import org.apache.commons.io.IOUtils;
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.compiler.DrlParser;
import org.drools.compiler.DroolsParserException;
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.BuilderResultLine;
import org.drools.guvnor.client.rpc.BulkTestRunResult;
import org.drools.guvnor.client.rpc.DetailedSerializationException;
import org.drools.guvnor.client.rpc.Module;
import org.drools.guvnor.client.rpc.ModuleService;
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.SnapshotComparisonPageRequest;
import org.drools.guvnor.client.rpc.SnapshotComparisonPageResponse;
import org.drools.guvnor.client.rpc.SnapshotDiffs;
import org.drools.guvnor.client.rpc.SnapshotInfo;
import org.drools.guvnor.client.rpc.ValidatedResponse;
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.contenthandler.ModelContentHandler;
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.lang.descr.PackageDescr;
import org.drools.lang.descr.TypeDeclarationDescr;
import org.drools.repository.AssetItem;
import org.drools.repository.AssetItemIterator;
import org.drools.repository.ModuleItem;
import org.drools.repository.RepositoryFilter;
import org.drools.repository.RulesRepository;
import org.drools.repository.RulesRepositoryException;
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.jboss.seam.remoting.annotations.WebRemote;
import org.jboss.seam.security.Identity;
import org.jboss.seam.security.annotations.LoggedIn;

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

@ApplicationScoped
@Named("org.drools.guvnor.client.rpc.PackageService")
public class RepositoryModuleService
        implements
        ModuleService {

    private static final long serialVersionUID = 901123;

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

    @Inject
    private RulesRepository rulesRepository;

    @Inject
    private ServiceSecurity serviceSecurity;

    @Inject
    private Identity identity;

    @Inject
    private RepositoryModuleOperations repositoryModuleOperations;

    @Inject
    private RepositoryAssetOperations repositoryAssetOperations;

    @Inject
    private ServiceImplementation serviceImplementation;

    /**
     * Role-based Authorization check: This method only returns modules that
     * the user has permission to access. User has permission to access the
     * particular module when: The user has a package.readonly role or higher
     * (i.e., package.admin, package.developer) to this module.
     */
    @WebRemote
    @LoggedIn
    public Module[] listModules() {
        return listModules(null);
    }

    @WebRemote
    @LoggedIn
    public Module[] listModules(String workspace) {
        RepositoryFilter pf = new ModuleFilter(identity);
        return repositoryModuleOperations.listModules(
                false,
                workspace,
                pf);
    }

    @WebRemote
    @LoggedIn
    public Module[] listArchivedModules() {
        return listArchivedModules(null);
    }

    @WebRemote
    @LoggedIn
    public Module[] listArchivedModules(String workspace) {
        return repositoryModuleOperations.listModules(
                true,
                workspace,
                new ModuleFilter(identity));
    }

    public Module loadGlobalModule() {
        return repositoryModuleOperations.loadGlobalModule();
    }

    @WebRemote
    @LoggedIn
    public void rebuildPackages() throws SerializationException {
        Iterator<ModuleItem> pkit = rulesRepository.listModules();
        StringBuilder errs = new StringBuilder();
        while (pkit.hasNext()) {
            ModuleItem pkg = pkit.next();
            try {
                BuilderResult builderResult = this.buildPackage(pkg.getUUID(),
                        true);
                if (builderResult != null) {
                    errs.append("Unable to build package name [").append(pkg.getName()).append("]\n");
                    StringBuilder buf = createStringBuilderFrom(builderResult);
                    log.warn(buf.toString());
                }
            } catch (Exception e) {
                e.printStackTrace();
                log.error("An error occurred building package [" + pkg.getName() + "]\n");
                errs.append("An error occurred building package [").append(pkg.getName()).append("]\n");
            }
        }
    }

    private StringBuilder createStringBuilderFrom(BuilderResult res) {
        StringBuilder buf = new StringBuilder();
        for (int i = 0; i < res.getLines().size(); i++) {
            buf.append(res.getLines().get(i).toString());
            buf.append('\n');
        }
        return buf;
    }

    @WebRemote
    @LoggedIn
    public String buildModuleSource(String moduleUUID) throws SerializationException {
        serviceSecurity.checkSecurityIsPackageDeveloperWithPackageUuid(moduleUUID);
        return repositoryModuleOperations.buildModuleSource(moduleUUID);
    }

    @WebRemote
    public String copyModule(String sourceModuleName,
                             String destModuleName) throws SerializationException {
        serviceSecurity.checkSecurityIsAdmin();
        return repositoryModuleOperations.copyModules(sourceModuleName,
                destModuleName);
    }

    @WebRemote
    @LoggedIn
    public void removeModule(String uuid) {
        serviceSecurity.checkSecurityIsPackageAdminWithPackageUuid(uuid);
        repositoryModuleOperations.removeModule(uuid);
    }

    @WebRemote
    @LoggedIn
    public String renameModule(String uuid,
                               String newName) {
        serviceSecurity.checkSecurityIsPackageAdminWithPackageUuid(uuid);

        return repositoryModuleOperations.renameModule(uuid,
                newName);
    }

    @WebRemote
    @LoggedIn
    public byte[] exportModules(String moduleName) {
        serviceSecurity.checkSecurityIsPackageAdminWithPackageName(moduleName);
        return repositoryModuleOperations.exportModules(moduleName);
    }

    @WebRemote
    @LoggedIn
    public void importPackages(byte[] byteArray,
                               boolean importAsNew) {
        repositoryModuleOperations.importPackages(byteArray,
                importAsNew);
    }

    @WebRemote
    public String createModule(String name,
                               String description,
                               String format) throws RulesRepositoryException {
        return repositoryModuleOperations.createModule(name,
                description,
                format);
    }

    @WebRemote
    public String createModule(String name,
                               String description,
                               String format,
                               String[] workspace) throws RulesRepositoryException {
        serviceSecurity.checkSecurityIsAdmin();
        return repositoryModuleOperations.createModule(name,
                description,
                format,
                workspace);
    }

    /*
     * @WebRemote public String createPackage(String name, String description,
     * String format) throws RulesRepositoryException {
     * serviceSecurity.checkSecurityIsAdmin(); return
     * repositoryPackageOperations.createPackage( name, description, new
     * String[]{} ); }
     */
    /*
     * @WebRemote public String createPackage(String name, String description,
     * String format, String[] workspace) throws RulesRepositoryException {
     * return createPackage( name, description, new String[]{} ); }
     */
    @WebRemote
    public String createSubModule(String name,
                                  String description,
                                  String parentNode) throws SerializationException {
        serviceSecurity.checkSecurityIsAdmin();
        return repositoryModuleOperations.createSubModule(name,
                description,
                parentNode);
    }

    @WebRemote
    @LoggedIn
    public Module loadModule(String uuid) {
        ModuleItem moduleItem = rulesRepository.loadModuleByUUID(uuid);
        // the uuid passed in is the uuid of that deployment bundle, not the
        // module uudi.
        // we have to figure out the module name.
        serviceSecurity.checkSecurityIsPackageReadOnlyWithPackageName(moduleItem.getName());
        return repositoryModuleOperations.loadModule(moduleItem);
    }

    @WebRemote
    @LoggedIn
    public ValidatedResponse validateModule(Module data) throws SerializationException {
        serviceSecurity.checkSecurityIsPackageDeveloperWithPackageUuid(data.getUuid());
        return repositoryModuleOperations.validateModule(data);
    }

    @WebRemote
    @LoggedIn
    public void saveModule(Module data) throws SerializationException {
        serviceSecurity.checkSecurityIsPackageDeveloperWithPackageUuid(data.getUuid());
        repositoryModuleOperations.saveModule(data);
    }

    @WebRemote
    @LoggedIn
    public BuilderResult buildPackage(String packageUUID,
                                      boolean force) throws SerializationException {
        return buildPackage(packageUUID,
                force,
                null,
                null,
                null,
                false,
                null,
                null,
                false,
                null);
    }

    @WebRemote
    @LoggedIn
    public BuilderResult buildPackage(String packageUUID,
                                      boolean force,
                                      String buildMode,
                                      String statusOperator,
                                      String statusDescriptionValue,
                                      boolean enableStatusSelector,
                                      String categoryOperator,
                                      String category,
                                      boolean enableCategorySelector,
                                      String customSelectorName) throws SerializationException {
        serviceSecurity.checkSecurityIsPackageDeveloperWithPackageUuid(packageUUID);
        return repositoryModuleOperations.buildModule(packageUUID,
                force,
                buildMode,
                statusOperator,
                statusDescriptionValue,
                enableStatusSelector,
                categoryOperator,
                category,
                enableCategorySelector,
                customSelectorName);
    }

    @WebRemote
    @LoggedIn
    public void createModuleSnapshot(String moduleName,
                                     String snapshotName,
                                     boolean replaceExisting,
                                     String comment,
                                     final String buildMode,
                                     final String statusOperator,
                                     final String statusValue,
                                     final boolean enableStatusSelector,
                                     final String categoryOperator,
                                     final String category,
                                     final boolean enableCategorySelector,
                                     final String customSelector) throws SerializationException {
        serviceSecurity.checkSecurityIsPackageAdminWithPackageName(moduleName);
        repositoryModuleOperations.createModuleSnapshot(moduleName,
                snapshotName,
                replaceExisting,
                comment,
                false,
                buildMode,
                statusOperator,
                statusValue,
                enableStatusSelector,
                categoryOperator,
                category,
                enableCategorySelector,
                customSelector);

    }
   
    @WebRemote
    @LoggedIn
    public void createModuleSnapshot(String moduleName,
                                     String snapshotName,
                                     boolean replaceExisting,
                                     String comment,
                                     boolean checkIsBinaryUpToDate,
                                     final String buildMode,
                                     final String statusOperator,
                                     final String statusValue,
                                     final boolean enableStatusSelector,
                                     final String categoryOperator,
                                     final String category,
                                     final boolean enableCategorySelector,
                                     final String customSelector) throws SerializationException {
        serviceSecurity.checkSecurityIsPackageAdminWithPackageName(moduleName);
        repositoryModuleOperations.createModuleSnapshot(moduleName,
                snapshotName,
                replaceExisting,
                comment,
                checkIsBinaryUpToDate,
                buildMode,
                statusOperator,
                statusValue,
                enableStatusSelector,
                categoryOperator,
                category,
                enableCategorySelector,
                customSelector);
    }
   
    @WebRemote
    @LoggedIn
    public void copyOrRemoveSnapshot(String moduleName,
                                     String snapshotName,
                                     boolean delete,
                                     String newSnapshotName) throws SerializationException {
        serviceSecurity.checkSecurityIsPackageAdminWithPackageName(moduleName);
        repositoryModuleOperations.copyOrRemoveSnapshot(moduleName,
                snapshotName,
                delete,
                newSnapshotName);
    }

    @WebRemote
    @LoggedIn
    public String[] listRulesInPackage(String packageName) throws SerializationException {
        serviceSecurity.checkSecurityIsPackageReadOnlyWithPackageName(packageName);
        return repositoryModuleOperations.listRulesInPackage(packageName);
    }

    @WebRemote
    @LoggedIn
    public String[] listImagesInModule(String moduleName) throws SerializationException {
        serviceSecurity.checkSecurityIsPackageReadOnlyWithPackageName(moduleName);
        return repositoryModuleOperations.listImagesInModule(moduleName);
    }

    @WebRemote
    public void rebuildSnapshots() throws SerializationException {
        serviceSecurity.checkSecurityIsAdmin();

        Iterator<ModuleItem> pkit = rulesRepository.listModules();
        while (pkit.hasNext()) {
            ModuleItem pkg = pkit.next();
            String[] snaps = rulesRepository.listModuleSnapshots(pkg.getName());
            for (String snapName : snaps) {
                ModuleItem snap = rulesRepository.loadModuleSnapshot(pkg.getName(),
                        snapName);
                BuilderResult builderResult = this.buildPackage(snap.getUUID(),
                        true);
                if (builderResult.hasLines()) {
                    StringBuilder stringBuilder = createStringBuilderFrom(builderResult);
                    throw new DetailedSerializationException("Unable to rebuild snapshot [" + snapName,
                            stringBuilder.toString() + "]");
                }
            }
        }
    }

    @WebRemote
    @LoggedIn
    public SnapshotInfo[] listSnapshots(String moduleName) {
        serviceSecurity.checkSecurityIsPackageDeveloperWithPackageName(moduleName);

        String[] snaps = rulesRepository.listModuleSnapshots(moduleName);
        SnapshotInfo[] snapshotInfos = new SnapshotInfo[snaps.length];
        for (int i = 0; i < snaps.length; i++) {
            ModuleItem moduleItem = rulesRepository.loadModuleSnapshot(moduleName,
                    snaps[i]);
            snapshotInfos[i] = moduleItemToSnapshotItem(snaps[i],
                    moduleItem);
        }
        return snapshotInfos;
    }

    @LoggedIn
    public SnapshotInfo loadSnapshotInfo(String packageName,
                                         String snapshotName) {
        serviceSecurity.checkSecurityIsPackageAdminWithPackageName(packageName);

        return moduleItemToSnapshotItem(
                snapshotName,
                rulesRepository.loadModuleSnapshot(
                        packageName,
                        snapshotName));
    }

    private SnapshotInfo moduleItemToSnapshotItem(String snapshotName,
                                                  ModuleItem packageItem) {
        SnapshotInfo snapshotInfo = new SnapshotInfo();
        snapshotInfo.setComment(packageItem.getCheckinComment());
        snapshotInfo.setName(snapshotName);
        snapshotInfo.setUuid(packageItem.getUUID());
        return snapshotInfo;
    }

    @WebRemote
    @LoggedIn
    public String[] listTypesInPackage(String packageUUID) throws SerializationException {
        serviceSecurity.checkSecurityPackageReadOnlyWithPackageUuid(packageUUID);

        ModuleItem pkg = this.rulesRepository.loadModuleByUUID(packageUUID);
        List<String> res = new ArrayList<String>();
        AssetItemIterator it = pkg.listAssetsByFormat(AssetFormats.MODEL,
                AssetFormats.DRL_MODEL);

        JarInputStream jis = null;

        try {
            while (it.hasNext()) {
                AssetItem asset = it.next();
                if (!asset.isArchived()) {
                    if (asset.getFormat().equals(AssetFormats.MODEL)) {
                        jis = typesForModel(res,
                                asset);
                    } else {
                        typesForOthers(res,
                                asset);
                    }

                }
            }
            return res.toArray(new String[res.size()]);
        } catch (IOException e) {
            log.error("Unable to read the jar files in the package: " + e.getMessage());
            throw new DetailedSerializationException("Unable to read the jar files in the package.",
                    e.getMessage());
        } finally {
            IOUtils.closeQuietly(jis);
        }

    }

    @WebRemote
    @LoggedIn
    public void updateDependency(String uuid,
                                 String dependencyPath) {
        ModuleItem item = rulesRepository.loadModuleByUUID(uuid);
        item.updateDependency(dependencyPath);
        item.checkin("Update dependency");
    }

    public String[] getDependencies(String uuid) {
        ModuleItem item = rulesRepository.loadModuleByUUID(uuid);
        return item.getDependencies();
    }

    private JarInputStream typesForModel(List<String> res,
                                         AssetItem asset) throws IOException {
        if (!asset.isBinary()) {
            return null;
        }
        if (asset.getBinaryContentAttachment() == null) {
            return null;
        }

        JarInputStream jis;
        jis = new JarInputStream(asset.getBinaryContentAttachment());
        JarEntry entry = null;
        while ((entry = jis.getNextJarEntry()) != null) {
            if (!entry.isDirectory()) {
                if (entry.getName().endsWith(".class")) {
                    res.add(ModelContentHandler.convertPathToName(entry.getName()));
                }
            }
        }
        return jis;
    }

    private void typesForOthers(List<String> res,
                                AssetItem asset) {
        // its delcared model
        DrlParser parser = new DrlParser();
        try {
            PackageDescr desc = parser.parse(asset.getContent());
            List<TypeDeclarationDescr> types = desc.getTypeDeclarations();
            for (TypeDeclarationDescr typeDeclarationDescr : types) {
                res.add(typeDeclarationDescr.getTypeName());
            }
        } catch (DroolsParserException e) {
            log.error("An error occurred parsing rule: " + e.getMessage());

        }
    }

    @LoggedIn
    public void installSampleRepository() throws SerializationException {
        rulesRepository.importRepository(this.getClass().getResourceAsStream("/mortgage-sample-repository.xml"));
        this.rebuildPackages();
        this.rebuildSnapshots();
    }

    /**
     * @deprecated in favour of
     *             {@link #compareSnapshots(SnapshotComparisonPageRequest)}
     */
    public SnapshotDiffs compareSnapshots(String moduleName,
                                          String firstSnapshotName,
                                          String secondSnapshotName) {
        return repositoryModuleOperations.compareSnapshots(moduleName,
                firstSnapshotName,
                secondSnapshotName);
    }

    public SnapshotComparisonPageResponse compareSnapshots(SnapshotComparisonPageRequest request) {
        if (request == null) {
            throw new IllegalArgumentException("request cannot be null");
        }
        if (request.getPageSize() != null && request.getPageSize() < 0) {
            throw new IllegalArgumentException("pageSize cannot be less than zero.");
        }

        return repositoryModuleOperations.compareSnapshots(request);
    }

    @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 ) {
                    //err.getErrs() returns a Collections$UnmodifiablerRandomAccessList that cannot be serialised
                    //by GWT. Hence we need to convert the errors into a List that can be serialised by GWT
                    List<BuilderResultLine> errors = new ArrayList<BuilderResultLine>();
                    for ( BuilderResultLine line : exception.getErrs() ) {
                        errors.add( line );
                    }
                    return new SingleScenarioResult( new ScenarioRunResult( errors ) );
                } else {
                    throw exception;
                }
            } else {
                throw new DetailedSerializationException( "Unable to run the scenario.",
                                                          e.getMessage() );
            }
        }
    }

    /*
     * 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 {
                BuilderResult result = repositoryModuleOperations.buildModule(packageItem,
                        false);
                if (result == null || result.getLines().size() == 0) {
                    RuleBase ruleBase = loadRuleBase(packageItem);
                    RuleBaseCache.getInstance().put(packageItem.getUUID(),
                            ruleBase);
                    return ruleBase;
                } else {
                    throw new DetailedSerializationException("Build error",
                            result.getLines());
                }
            }

        }
    }

    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;
    }

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

        RuleBase ruleBase = loadCacheRuleBase(item);
        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 : serviceImplementation.loadWorkItemDefinitions(item.getUUID())) {
            workingMemory.getWorkItemManager().registerWorkItemHandler(portableWorkDefinition.getName(),
                    workItemHandlerStub);
        }

        //Run Test Scenario
        try {
            AuditLogReporter logger = new AuditLogReporter(workingMemory);
            ClassLoader 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;
    }

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

    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());
            }

        }
    }

}
TOP

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

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.