Package org.drools.agent

Source Code of org.drools.agent.KnowledgeAgentTest

package org.drools.agent;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import junit.framework.TestCase;

import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.builder.impl.KnowledgeBuilderImpl;
import org.drools.command.runtime.rule.InsertObjectCommand;
import org.drools.core.util.DroolsStreamUtils;
import org.drools.core.util.FileManager;
import org.drools.definition.KnowledgePackage;
import org.drools.event.knowledgeagent.AfterChangeSetAppliedEvent;
import org.drools.event.knowledgeagent.AfterChangeSetProcessedEvent;
import org.drools.event.knowledgeagent.AfterResourceProcessedEvent;
import org.drools.event.knowledgeagent.BeforeChangeSetAppliedEvent;
import org.drools.event.knowledgeagent.BeforeChangeSetProcessedEvent;
import org.drools.event.knowledgeagent.BeforeResourceProcessedEvent;
import org.drools.event.knowledgeagent.KnowledgeAgentEventListener;
import org.drools.event.knowledgeagent.KnowledgeBaseUpdatedEvent;
import org.drools.event.knowledgeagent.ResourceCompilationFailedEvent;
import org.drools.io.ResourceChangeScannerConfiguration;
import org.drools.io.ResourceFactory;
import org.drools.io.impl.ResourceChangeNotifierImpl;
import org.drools.io.impl.ResourceChangeScannerImpl;
import org.drools.runtime.StatefulKnowledgeSession;
import org.drools.runtime.StatelessKnowledgeSession;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.handler.ResourceHandler;

public class KnowledgeAgentTest extends TestCase {

    FileManager fileManager;
    private Server server;
    private final Object lock = new Object();
    private volatile boolean kbaseUpdated;

    @Override
    protected void setUp() throws Exception {
        fileManager = new FileManager();
        fileManager.setUp();
        ((ResourceChangeScannerImpl) ResourceFactory.getResourceChangeScannerService()).reset();

        ResourceFactory.getResourceChangeNotifierService().start();
        ResourceFactory.getResourceChangeScannerService().start();

        this.server = new Server(0);
        ResourceHandler resourceHandler = new ResourceHandler();
        resourceHandler.setResourceBase(fileManager.getRootDirectory().getPath());

        server.setHandler(resourceHandler);

        server.start();

        this.kbaseUpdated = false;
    }

    private int getPort() {
        return this.server.getConnectors()[0].getLocalPort();
    }

    @Override
    protected void tearDown() throws Exception {
        fileManager.tearDown();
        ResourceFactory.getResourceChangeNotifierService().stop();
        ResourceFactory.getResourceChangeScannerService().stop();
        ((ResourceChangeNotifierImpl) ResourceFactory.getResourceChangeNotifierService()).reset();
        ((ResourceChangeScannerImpl) ResourceFactory.getResourceChangeScannerService()).reset();

        server.stop();
    }

    public void testModifyFileUrl() throws Exception {
        String rule1 = this.createDefaultRule("rule1");
        File f1 = fileManager.newFile("rule1.drl");
        Writer output = new BufferedWriter(new FileWriter(f1));
        output.write(rule1);
        output.close();

        String rule2 = this.createDefaultRule("rule2");

        File f2 = fileManager.newFile("rule2.drl");
        output = new BufferedWriter(new FileWriter(f2));
        output.write(rule2);
        output.close();

        String xml = "";
        xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
        xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
        xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set drools-change-set-5.0.xsd' >";
        xml += "    <add> ";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/rule1.drl' type='DRL' />";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/rule2.drl' type='DRL' />";
        xml += "    </add> ";
        xml += "</change-set>";
        File fxml = fileManager.newFile("changeset.xml");
        output = new BufferedWriter(new FileWriter(fxml));
        output.write(xml);
        output.close();

        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();

        ResourceChangeScannerConfiguration sconf = ResourceFactory.getResourceChangeScannerService().newResourceChangeScannerConfiguration();
        sconf.setProperty("drools.resource.scanner.interval", "2");
        ResourceFactory.getResourceChangeScannerService().configure(sconf);

        KnowledgeAgentConfiguration aconf = KnowledgeAgentFactory.newKnowledgeAgentConfiguration();
        aconf.setProperty("drools.agent.scanDirectories", "true");
        aconf.setProperty("drools.agent.scanResources", "true");
        aconf.setProperty("drools.agent.newInstance", "true");
        KnowledgeAgent kagent = KnowledgeAgentFactory.newKnowledgeAgent(
                "test agent", kbase, aconf);

        assertEquals("test agent", kagent.getName());

        kagent.applyChangeSet(ResourceFactory.newUrlResource(fxml.toURI().toURL()));
        kbaseUpdated = false;

        StatefulKnowledgeSession ksession = kagent.getKnowledgeBase().newStatefulKnowledgeSession();
        List<String> list = new ArrayList<String>();
        ksession.setGlobal("list", list);
        ksession.fireAllRules();
        ksession.dispose();

        assertEquals(2, list.size());
        assertTrue(list.contains("rule1"));
        assertTrue(list.contains("rule2"));

        list.clear();

        // have to sleep here as linux lastModified does not do milliseconds
        // http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&f=1&t=019789
        Thread.sleep(2000);

        rule1 = this.createDefaultRule("rule3");

        output = new BufferedWriter(new FileWriter(f1));
        output.write(rule1);
        output.close();
        Thread.sleep(3000);

        ksession = kagent.getKnowledgeBase().newStatefulKnowledgeSession();
        list = new ArrayList<String>();
        ksession.setGlobal("list", list);
        ksession.fireAllRules();
        ksession.dispose();

        assertEquals(2, list.size());

        assertTrue(list.contains("rule3"));
        assertTrue(list.contains("rule2"));
        kagent.monitorResourceChangeEvents(false);
    }

    /**
     * Tests that if we change a ChangeSet that is referenced by another change
     * set or added by another ChangeSet, that the changes are picked up.
     *
     * @throws Exception
     *             If an unexpected exception occurs.
     */
    public void testChangeSetInChangeSet() throws Exception {
        String rule1 = this.createDefaultRule("rule1");
        File f1 = fileManager.newFile("rule1.drl");
        Writer output = new BufferedWriter(new FileWriter(f1));
        output.write(rule1);
        output.close();

        String rule2 = this.createDefaultRule("rule2");
        File f2 = fileManager.newFile("rule2.drl");
        output = new BufferedWriter(new FileWriter(f2));
        output.write(rule2);
        output.close();

        String xml1 = "";
        xml1 += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
        xml1 += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
        xml1 += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set drools-change-set-5.0.xsd' >";
        xml1 += "    <add> ";
        xml1 += "        <resource source='http://localhost:" + this.getPort() + "/rule1.drl' type='DRL' />";
        xml1 += "        <resource source='http://localhost:" + this.getPort() + "/rule2.drl' type='DRL' />";
        xml1 += "    </add> ";
        xml1 += "</change-set>";
        File fxml1 = fileManager.newFile("changeset2.xml");
        output = new BufferedWriter(new FileWriter(fxml1));
        output.write(xml1);
        output.close();

        String xml2 = "";
        xml2 += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
        xml2 += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
        xml2 += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set drools-change-set-5.0.xsd' >";
        xml2 += "    <add> ";
        xml2 += "        <resource source='http://localhost:" + this.getPort() + "/changeset2.xml' type='CHANGE_SET' />";
        xml2 += "    </add> ";
        xml2 += "</change-set>";
        File fxml2 = fileManager.newFile("changeset.xml");
        output = new BufferedWriter(new FileWriter(fxml2));
        output.write(xml2);
        output.close();

        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();

        KnowledgeAgent kagent = this.createKAgent(kbase);

        kagent.applyChangeSet(ResourceFactory.newUrlResource(fxml2.toURI().toURL()));
        kbaseUpdated = false;

        StatefulKnowledgeSession ksession = kagent.getKnowledgeBase().newStatefulKnowledgeSession();
        List<String> list = new ArrayList<String>();
        ksession.setGlobal("list", list);
        ksession.fireAllRules();
        ksession.dispose();

        assertEquals(2, list.size());
        assertTrue(list.contains("rule1"));
        assertTrue(list.contains("rule2"));

        list.clear();

        // have to sleep here as linux lastModified does not do milliseconds
        // http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&f=1&t=019789
        Thread.sleep(2000);

        rule1 = this.createDefaultRule("rule3");
        output = new BufferedWriter(new FileWriter(f1));
        output.write(rule1);
        output.close();

        this.waitUntilKBaseUpdate();

        ksession = kagent.getKnowledgeBase().newStatefulKnowledgeSession();
        list = new ArrayList<String>();
        ksession.setGlobal("list", list);
        ksession.fireAllRules();
        ksession.dispose();

        assertEquals(2, list.size());

        assertTrue(list.contains("rule3"));
        assertTrue(list.contains("rule2"));

        kagent.monitorResourceChangeEvents(false);
    }

    public void testModifyFileUrlWithStateless() throws Exception {
        String rule1 = this.createDefaultRule("rule1");
        File f1 = fileManager.newFile("rule1.drl");
        Writer output = new BufferedWriter(new FileWriter(f1));
        output.write(rule1);
        output.close();

        String rule2 = this.createDefaultRule("rule2");
        File f2 = fileManager.newFile("rule2.drl");
        output = new BufferedWriter(new FileWriter(f2));
        output.write(rule2);
        output.close();

        String xml = "";
        xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
        xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
        xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set drools-change-set-5.0.xsd' >";
        xml += "    <add> ";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/rule1.drl' type='DRL' />";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/rule2.drl' type='DRL' />";
        xml += "    </add> ";
        xml += "</change-set>";
        File fxml = fileManager.newFile("changeset.xml");
        output = new BufferedWriter(new FileWriter(fxml));
        output.write(xml);
        output.close();

        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();

        KnowledgeAgent kagent = this.createKAgent(kbase);

        kagent.applyChangeSet(ResourceFactory.newUrlResource(fxml.toURI().toURL()));
        kbaseUpdated = false;

        StatelessKnowledgeSession ksession = kagent.newStatelessKnowledgeSession();
        List<String> list = new ArrayList<String>();
        ksession.setGlobal("list", list);
        ksession.execute("hello");

        assertEquals(2, list.size());
        assertTrue(list.contains("rule1"));
        assertTrue(list.contains("rule2"));

        list.clear();

        // have to sleep here as linux lastModified does not do milliseconds
        // http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&f=1&t=019789
        Thread.sleep(2000);

        rule1 = this.createDefaultRule("rule3");
        System.out.println("root : " + f1.getPath());
        output = new BufferedWriter(new FileWriter(f1));
        output.write(rule1);
        output.close();

        this.waitUntilKBaseUpdate();

        ksession.execute("hello");

        assertEquals(2, list.size());

        assertTrue(list.contains("rule3"));
        assertTrue(list.contains("rule2"));
        kagent.monitorResourceChangeEvents(false);
    }

    public void testModifyPackageUrl() throws Exception {
        String rule1 = this.createDefaultRule("rule1");

        String rule2 = this.createDefaultRule("rule2");

        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        kbuilder.add(ResourceFactory.newByteArrayResource(rule1.getBytes()),
                ResourceType.DRL);
        kbuilder.add(ResourceFactory.newByteArrayResource(rule2.getBytes()),
                ResourceType.DRL);
        if (kbuilder.hasErrors()) {
            fail(kbuilder.getErrors().toString());
        }
        KnowledgePackage pkg = (KnowledgePackage) kbuilder.getKnowledgePackages().iterator().next();
        writePackage(pkg, fileManager.newFile("pkg1.pkg"));

        String xml = "";
        xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
        xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
        xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set drools-change-set-5.0.xsd' >";
        xml += "    <add> ";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/pkg1.pkg' type='PKG' />";
        xml += "    </add> ";
        xml += "</change-set>";
        File fxml = fileManager.newFile("changeset.xml");
        Writer output = new BufferedWriter(new FileWriter(fxml));
        output.write(xml);
        output.close();

        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();

        KnowledgeAgent kagent = this.createKAgent(kbase);

        kagent.applyChangeSet(ResourceFactory.newUrlResource(fxml.toURI().toURL()));
        kbaseUpdated = false;

        StatefulKnowledgeSession ksession = kagent.getKnowledgeBase().newStatefulKnowledgeSession();
        List<String> list = new ArrayList<String>();
        ksession.setGlobal("list", list);
        ksession.fireAllRules();
        ksession.dispose();

        assertEquals(2, list.size());
        assertTrue(list.contains("rule1"));
        assertTrue(list.contains("rule2"));

        list.clear();

        // have to sleep here as linux lastModified does not do milliseconds
        // http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&f=1&t=019789
        Thread.sleep(2000);

        rule1 = this.createDefaultRule("rule3");

        kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        kbuilder.add(ResourceFactory.newByteArrayResource(rule1.getBytes()),
                ResourceType.DRL);
        kbuilder.add(ResourceFactory.newByteArrayResource(rule2.getBytes()),
                ResourceType.DRL);
        if (kbuilder.hasErrors()) {
            fail(kbuilder.getErrors().toString());
        }
        pkg = (KnowledgePackage) kbuilder.getKnowledgePackages().iterator().next();
        writePackage(pkg, fileManager.newFile("pkg1.pkg"));

        this.waitUntilKBaseUpdate();

        ksession = kagent.getKnowledgeBase().newStatefulKnowledgeSession();
        list = new ArrayList<String>();
        ksession.setGlobal("list", list);
        ksession.fireAllRules();
        ksession.dispose();

        assertEquals(2, list.size());

        assertTrue(list.contains("rule3"));
        assertTrue(list.contains("rule2"));
        kagent.monitorResourceChangeEvents(false);
    }

    public void testDeletePackageUrl() throws Exception {
        String rule1 = this.createDefaultRule("rule1","org.drools.test1");

        String rule2 = this.createDefaultRule("rule2","org.drools.test2");

        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        kbuilder.add(ResourceFactory.newByteArrayResource(rule1.getBytes()),
                ResourceType.DRL);
        kbuilder.add(ResourceFactory.newByteArrayResource(rule2.getBytes()),
                ResourceType.DRL);
        if (kbuilder.hasErrors()) {
            fail(kbuilder.getErrors().toString());
        }

        Map<String, KnowledgePackage> map = new HashMap<String, KnowledgePackage>();
        for (KnowledgePackage pkg : kbuilder.getKnowledgePackages()) {
            map.put(pkg.getName(), pkg);
        }
        writePackage((KnowledgePackage) map.get("org.drools.test1"),
                fileManager.newFile("pkg1.pkg"));
        writePackage((KnowledgePackage) map.get("org.drools.test2"),
                fileManager.newFile("pkg2.pkg"));

        String xml = "";
        xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
        xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
        xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set drools-change-set-5.0.xsd' >";
        xml += "    <add> ";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/pkg1.pkg' type='PKG' />";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/pkg2.pkg' type='PKG' />";
        xml += "    </add> ";
        xml += "</change-set>";

        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();

        KnowledgeAgent kagent = this.createKAgent(kbase);

        kagent.applyChangeSet(ResourceFactory.newByteArrayResource(xml.getBytes()));
        kbaseUpdated = false;

        StatefulKnowledgeSession ksession = kagent.getKnowledgeBase().newStatefulKnowledgeSession();
        List<String> list = new ArrayList<String>();
        ksession.setGlobal("list", list);
        ksession.fireAllRules();
        ksession.dispose();

        assertEquals(2, list.size());
        assertTrue(list.contains("rule1"));
        assertTrue(list.contains("rule2"));

        list.clear();

        xml = "";
        xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
        xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
        xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set drools-change-set-5.0.xsd' >";
        xml += "    <remove> ";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/pkg2.pkg' type='PKG' />";
        xml += "    </remove> ";
        xml += "</change-set>";

        kagent.applyChangeSet(ResourceFactory.newByteArrayResource(xml.getBytes()));
        kbaseUpdated = false;

        ksession = kagent.getKnowledgeBase().newStatefulKnowledgeSession();
        list = new ArrayList<String>();
        ksession.setGlobal("list", list);
        ksession.fireAllRules();
        ksession.dispose();

        assertEquals(1, list.size());

        assertTrue(list.contains("rule1"));
        kagent.monitorResourceChangeEvents(false);
    }

    public void testOldSchoolPackageUrl() throws Exception {
        String rule1 = this.createDefaultRule("rule1");

        String rule2 = this.createDefaultRule("rule2");

        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        kbuilder.add(ResourceFactory.newByteArrayResource(rule1.getBytes()),
                ResourceType.DRL);
        kbuilder.add(ResourceFactory.newByteArrayResource(rule2.getBytes()),
                ResourceType.DRL);
        if (kbuilder.hasErrors()) {
            fail(kbuilder.getErrors().toString());
        }

        KnowledgeBuilderImpl kbi = (KnowledgeBuilderImpl) kbuilder;

        // KnowledgePackage pkg = ( KnowledgePackage )
        // kbuilder.getKnowledgePackages().iterator().next();
        writePackage(kbi.getPackageBuilder().getPackage(), fileManager.newFile("pkgold.pkg"));

        String xml = "";
        xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
        xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
        xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set drools-change-set-5.0.xsd' >";
        xml += "    <add> ";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/pkgold.pkg' type='PKG' />";
        xml += "    </add> ";
        xml += "</change-set>";
        File fxml = fileManager.newFile("changeset.xml");
        Writer output = new BufferedWriter(new FileWriter(fxml));
        output.write(xml);
        output.close();

        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();

        KnowledgeAgent kagent = this.createKAgent(kbase);

        kagent.applyChangeSet(ResourceFactory.newUrlResource(fxml.toURI().toURL()));
        kbaseUpdated = false;


        StatefulKnowledgeSession ksession = kagent.getKnowledgeBase().newStatefulKnowledgeSession();
        List<String> list = new ArrayList<String>();
        ksession.setGlobal("list", list);
        ksession.fireAllRules();
        ksession.dispose();

        assertEquals(2, list.size());
        assertTrue(list.contains("rule1"));
        assertTrue(list.contains("rule2"));

    }

    public void testModifyFile() throws IOException, InterruptedException {
        String rule1 = this.createDefaultRule("rule1");
        File f1 = fileManager.newFile("rule1.drl");
        Writer output = new BufferedWriter(new FileWriter(f1));
        output.write(rule1);
        output.close();

        String rule2 = this.createDefaultRule("rule2");
        File f2 = fileManager.newFile("rule2.drl");
        output = new BufferedWriter(new FileWriter(f2));
        output.write(rule2);
        output.close();

        String xml = "";
        xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
        xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
        xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set drools-change-set-5.0.xsd' >";
        xml += "    <add> ";
        xml += "        <resource source='" + f1.toURI().toURL()
                + "' type='DRL' />";
        xml += "        <resource source='" + f2.toURI().toURL()
                + "' type='DRL' />";
        xml += "    </add> ";
        xml += "</change-set>";
        File fxml = fileManager.newFile("changeset.xml");
        output = new BufferedWriter(new FileWriter(fxml));
        output.write(xml);
        output.close();

        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();

        KnowledgeAgent kagent = this.createKAgent(kbase);

        kagent.applyChangeSet(ResourceFactory.newUrlResource(fxml.toURI().toURL()));
        kbaseUpdated = false;


        StatefulKnowledgeSession ksession = kagent.getKnowledgeBase().newStatefulKnowledgeSession();
        List<String> list = new ArrayList<String>();
        ksession.setGlobal("list", list);
        ksession.fireAllRules();
        ksession.dispose();

        assertEquals(2, list.size());
        assertTrue(list.contains("rule1"));
        assertTrue(list.contains("rule2"));

        list.clear();

        // have to sleep here as linux lastModified does not do milliseconds
        // http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&f=1&t=019789
        Thread.sleep(2000);

        rule1 = this.createDefaultRule("rule3");
        output = new BufferedWriter(new FileWriter(f1));
        output.write(rule1);
        output.close();

        this.waitUntilKBaseUpdate();

        ksession = kagent.getKnowledgeBase().newStatefulKnowledgeSession();
        list = new ArrayList<String>();
        ksession.setGlobal("list", list);
        ksession.fireAllRules();
        ksession.dispose();

        assertEquals(2, list.size());

        assertTrue(list.contains("rule3"));
        assertTrue(list.contains("rule2"));
        kagent.monitorResourceChangeEvents(false);
    }

    public void testModifyDirectory() throws IOException, InterruptedException {
        // adds 2 files to a dir and executes then adds one and removes one and
        // detects changes
        String rule1 = this.createDefaultRule("rule1");
        File f1 = fileManager.newFile("rule1.drl");

        Writer output = new BufferedWriter(new FileWriter(f1));
        output.write(rule1);
        output.close();

        String rule2 = this.createDefaultRule("rule2");
        File f2 = fileManager.newFile("rule2.drl");
        output = new BufferedWriter(new FileWriter(f2));
        output.write(rule2);
        output.close();

        String xml = "";
        xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
        xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
        xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set drools-change-set-5.0.xsd' >";
        xml += "    <add> ";
        xml += "        <resource source='"
                + f1.getParentFile().toURI().toURL() + "' type='DRL' />";
        xml += "    </add> ";
        xml += "</change-set>";
        File newDir = fileManager.newFile("changeset");
        newDir.mkdir();
        File fxml = fileManager.newFile(newDir, "changeset.xml");
        output = new BufferedWriter(new FileWriter(fxml));
        output.write(xml);
        output.close();

        // KnowledgeBuilder kbuilder =
        // KnowledgeBuilderFactory.newKnowledgeBuilder();
        // kbuilder.add( ResourceFactory.newUrlResource( fxml.toURI().toURL() ),
        // ResourceType.ChangeSet );
        // assertFalse( kbuilder.hasErrors() );

        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
        // kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );

        KnowledgeAgent kagent = this.createKAgent(kbase);

        kagent.applyChangeSet(ResourceFactory.newUrlResource(fxml.toURI().toURL()));
        kbaseUpdated = false;

        StatefulKnowledgeSession ksession = kagent.getKnowledgeBase().newStatefulKnowledgeSession();
        List<String> list = new ArrayList<String>();
        ksession.setGlobal("list", list);
        ksession.fireAllRules();
        ksession.dispose();

        assertEquals(2, list.size());
        assertTrue(list.contains("rule1"));
        assertTrue(list.contains("rule2"));

        list.clear();

        Thread.sleep(2000); // give it 2 seconds to detect and build the changes
        String rule3 = this.createDefaultRule("rule3");
        File f3 = fileManager.newFile("rule3.drl");
        output = new BufferedWriter(new FileWriter(f3));
        output.write(rule3);
        output.close();

        assertTrue(f1.delete());

        this.waitUntilKBaseUpdate();

        ksession = kagent.getKnowledgeBase().newStatefulKnowledgeSession();
        list = new ArrayList<String>();
        ksession.setGlobal("list", list);
        ksession.fireAllRules();
        ksession.dispose();

        assertEquals(2, list.size());
        assertTrue(list.contains("rule2"));
        assertTrue(list.contains("rule3"));

        kagent.monitorResourceChangeEvents(false);
    }

    public void testModifyFileInDirectory() throws Exception {
        // Create the test directory
        File testDirectory = fileManager.newFile("test");
        testDirectory.mkdir();

        String rule1 = this.createDefaultRule("rule1");
        File f1 = fileManager.newFile(testDirectory, "rule1.drl");
        Writer output = new BufferedWriter(new FileWriter(f1));
        output.write(rule1);
        output.close();

        String rule2 = this.createDefaultRule("rule2");
        File f2 = fileManager.newFile(testDirectory, "rule2.drl");
        output = new BufferedWriter(new FileWriter(f2));
        output.write(rule2);
        output.close();

        String xml = "";
        xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
        xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
        xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set drools-change-set-5.0.xsd' >";
        xml += "    <add> ";
        xml += "        <resource source='file:"
                + fileManager.getRootDirectory().getAbsolutePath()
                + "/test' type='DRL' />";
        xml += "    </add> ";
        xml += "</change-set>";
        File fxml = fileManager.newFile("changeset.xml");
        output = new BufferedWriter(new FileWriter(fxml));
        output.write(xml);
        output.close();

        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();

        KnowledgeAgent kagent = this.createKAgent(kbase);

        kagent.applyChangeSet(ResourceFactory.newUrlResource(fxml.toURI().toURL()));
        kbaseUpdated = false;


        StatefulKnowledgeSession ksession = kagent.getKnowledgeBase().newStatefulKnowledgeSession();
        List<String> list = new ArrayList<String>();
        ksession.setGlobal("list", list);
        ksession.fireAllRules();
        ksession.dispose();

        assertEquals(2, list.size());
        assertTrue(list.contains("rule1"));
        assertTrue(list.contains("rule2"));

        list.clear();

        // have to sleep here as linux lastModified does not do milliseconds
        // http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&f=1&t=019789
        Thread.sleep(2000);

        rule1 = this.createDefaultRule("rule3");
        output = new BufferedWriter(new FileWriter(f1));
        output.write(rule1);
        output.close();

        this.waitUntilKBaseUpdate();

        ksession = kagent.getKnowledgeBase().newStatefulKnowledgeSession();
        list = new ArrayList<String>();
        ksession.setGlobal("list", list);
        ksession.fireAllRules();
        ksession.dispose();

        assertEquals(2, list.size());

        assertTrue(list.contains("rule3"));
        assertTrue(list.contains("rule2"));
        kagent.monitorResourceChangeEvents(false);
    }

    public void testStatelessWithCommands() throws Exception {
        String rule1 = this.createDefaultRule("rule1");
        File f1 = fileManager.newFile("rule1.drl");

        Writer output = new BufferedWriter(new FileWriter(f1));
        output.write(rule1);
        output.close();

        String rule2 = this.createDefaultRule("rule2");
        File f2 = fileManager.newFile("rule2.drl");
        output = new BufferedWriter(new FileWriter(f2));
        output.write(rule2);
        output.close();

        String xml = "";
        xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
        xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
        xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set drools-change-set-5.0.xsd' >";
        xml += "    <add> ";
        xml += "        <resource source='"
                + f1.getParentFile().toURI().toURL() + "' type='DRL' />";
        xml += "    </add> ";
        xml += "</change-set>";
        File newDir = fileManager.newFile("changeset");
        newDir.mkdir();
        File fxml = fileManager.newFile(newDir, "changeset.xml");
        output = new BufferedWriter(new FileWriter(fxml));
        output.write(xml);
        output.close();

        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();

        KnowledgeAgent kagent = this.createKAgent(kbase);

        kagent.applyChangeSet(ResourceFactory.newUrlResource(fxml.toURI().toURL()));
        kbaseUpdated = false;


        StatelessKnowledgeSession ksession = kagent.newStatelessKnowledgeSession();

        List<String> list = new ArrayList<String>();
        ksession.setGlobal("list", list);

        ksession.execute( new InsertObjectCommand("hello") );

        assertEquals(2, list.size());
        assertTrue(list.contains("rule1"));
        assertTrue(list.contains("rule2"));
    }

    private static void writePackage(Object pkg, File p1file)
            throws IOException, FileNotFoundException {
        FileOutputStream out = new FileOutputStream(p1file);
        try {
            DroolsStreamUtils.streamOut(out, pkg);
        } finally {
            out.close();
        }
    }

    private KnowledgeAgent createKAgent(KnowledgeBase kbase) {
        ResourceChangeScannerConfiguration sconf = ResourceFactory.getResourceChangeScannerService().newResourceChangeScannerConfiguration();
        sconf.setProperty("drools.resource.scanner.interval", "2");
        ResourceFactory.getResourceChangeScannerService().configure(sconf);

        KnowledgeAgentConfiguration aconf = KnowledgeAgentFactory.newKnowledgeAgentConfiguration();
        aconf.setProperty("drools.agent.scanDirectories", "true");
        aconf.setProperty("drools.agent.scanResources", "true");
        // Testing incremental build here
        aconf.setProperty("drools.agent.newInstance", "true");

        KnowledgeAgent kagent = KnowledgeAgentFactory.newKnowledgeAgent(
                "test agent", kbase, aconf);

        kagent.addEventListener(new KnowledgeAgentEventListener() {

            public void beforeChangeSetApplied(BeforeChangeSetAppliedEvent event) {
            }

            public void afterChangeSetApplied(AfterChangeSetAppliedEvent event) {
            }

            public void beforeChangeSetProcessed(BeforeChangeSetProcessedEvent event) {
            }

            public void afterChangeSetProcessed(AfterChangeSetProcessedEvent event) {
            }

            public void beforeResourceProcessed(BeforeResourceProcessedEvent event) {
            }

            public void afterResourceProcessed(AfterResourceProcessedEvent event) {
            }

            public void knowledgeBaseUpdated(KnowledgeBaseUpdatedEvent event) {
                System.out.println("KBase was updated");
                synchronized (lock) {
                    kbaseUpdated = true;
                    lock.notifyAll();
                }
            }

            public void resourceCompilationFailed(ResourceCompilationFailedEvent event) {
            }
        });

        assertEquals("test agent", kagent.getName());

        return kagent;
    }

    private String createDefaultRule(String name){
        return this.createDefaultRule(name, null);
    }

    private String createDefaultRule(String name, String packageName){
        StringBuilder rule = new StringBuilder();
        if (packageName == null){
            rule.append("package org.drools.test\n");
        }else{
            rule.append("package ");
            rule.append(packageName);
            rule.append("\n");
        }
        rule.append("global java.util.List list\n");
        rule.append("rule ");
        rule.append(name);
        rule.append("\n");
        rule.append("when\n");
        rule.append("then\n");
        rule.append("list.add( drools.getRule().getName() );\n");
        rule.append("end\n");

        return rule.toString();
    }

    private void waitUntilKBaseUpdate() {
        synchronized (lock) {
            while (!kbaseUpdated) {
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                }
                System.out.println("Waking up!");
            }
            kbaseUpdated = false;
        }
    }
}
TOP

Related Classes of org.drools.agent.KnowledgeAgentTest

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.