/* * Copyright 2015 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * * 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.kie.scanner; import static java.util.Arrays.asList; import static org.junit.Assert.*; import static org.kie.scanner.MavenRepository.getMavenRepository; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import org.apache.commons.io.FileUtils; import org.apache.maven.model.Dependency; import org.apache.maven.repository.internal.MavenRepositorySystemUtils; import org.drools.compiler.kie.builder.impl.InternalKieModule; import org.drools.compiler.kie.builder.impl.InternalKieScanner; import org.drools.compiler.kie.builder.impl.KieFileSystemImpl; import org.drools.core.util.FileManager; import org.eclipse.aether.DefaultRepositorySystemSession; import org.eclipse.aether.artifact.Artifact; import org.eclipse.aether.artifact.DefaultArtifact; import org.eclipse.aether.repository.LocalRepository; import org.eclipse.aether.repository.LocalRepositoryManager; import org.hamcrest.CoreMatchers; import org.junit.After; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.kie.api.KieServices; import org.kie.api.builder.KieBuilder; import org.kie.api.builder.KieFileSystem; import org.kie.api.builder.KieScanner; import org.kie.api.builder.Message; import org.kie.api.builder.ReleaseId; import org.kie.api.builder.model.KieModuleModel; import org.kie.api.event.kiescanner.KieScannerEvent; import org.kie.api.event.kiescanner.KieScannerEventListener; import org.kie.api.event.kiescanner.KieScannerStatusChangeEvent; import org.kie.api.event.kiescanner.KieScannerUpdateResultsEvent; import org.kie.api.runtime.KieContainer; import org.kie.api.runtime.KieSession; import org.kie.scanner.embedder.MavenEmbedderUtils; import org.kie.scanner.event.KieScannerStatusChangeEventImpl; import org.kie.scanner.event.KieScannerUpdateResultsEventImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @RunWith(Parameterized.class) public class KieRepositoryScannerTest extends AbstractKieCiTest { private static final Logger LOG = LoggerFactory.getLogger(KieRepositoryScannerTest.class); private final boolean useWiredComponentProvider; private FileManager fileManager; @Parameterized.Parameters(name = "Manually wired component provider={0}") public static Collection modes() { Object[][] manuallyWiredProvider = new Object[][] { { true }, { false } }; return Arrays.asList(manuallyWiredProvider); } public KieRepositoryScannerTest( boolean useWiredComponentProvider) { this.useWiredComponentProvider = useWiredComponentProvider; } @Before public void setUp() throws Exception { MavenEmbedderUtils.enforceWiredComponentProvider = useWiredComponentProvider; this.fileManager = new FileManager(); this.fileManager.setUp(); ReleaseId releaseId = KieServices.Factory.get().newReleaseId("org.kie", "scanner-test", "1.0-SNAPSHOT"); } @After public void tearDown() throws Exception { this.fileManager.tearDown(); MavenEmbedderUtils.enforceWiredComponentProvider = false; } private void resetFileManager() { this.fileManager.tearDown(); this.fileManager = new FileManager(); this.fileManager.setUp(); } @Test public void testKScanner() throws Exception { KieServices ks = KieServices.Factory.get(); ReleaseId releaseId = ks.newReleaseId("org.kie", "scanner-test", "1.0-SNAPSHOT"); InternalKieModule kJar1 = createKieJar(ks, releaseId, "rule1", "rule2"); KieContainer kieContainer = ks.newKieContainer(releaseId); MavenRepository repository = getMavenRepository(); repository.installArtifact(releaseId, kJar1, createKPom(fileManager, releaseId)); // create a ksesion and check it works as expected KieSession ksession = kieContainer.newKieSession("KSession1"); checkKSession(ksession, "rule1", "rule2"); // create a new kjar InternalKieModule kJar2 = createKieJar(ks, releaseId, "rule2", "rule3"); // deploy it on maven repository.installArtifact(releaseId, kJar2, createKPom(fileManager, releaseId)); // since I am not calling start() on the scanner it means it won't have automatic scheduled scanning KieScanner scanner = ks.newKieScanner(kieContainer); // scan the maven repo to get the new kjar version and deploy it on the kcontainer scanner.scanNow(); // create a ksesion and check it works as expected KieSession ksession2 = kieContainer.newKieSession("KSession1"); checkKSession(ksession2, "rule2", "rule3"); ks.getRepository().removeKieModule(releaseId); } @Test @Ignore("used only for check performances") public void testKScannerWithDependencies() throws Exception { KieServices ks = KieServices.Factory.get(); ReleaseId releaseIdNoDep = ks.newReleaseId( "org.kie", "test-no-dep", "1.0-SNAPSHOT" ); ReleaseId releaseIdWithDep = ks.newReleaseId( "org.kie", "test-with-dep", "1.0-SNAPSHOT" ); long start = System.nanoTime(); InternalKieModule kJar1 = createKieJar( ks, releaseIdNoDep, false, "rule1" ); KieContainer kieContainer1 = ks.newKieContainer( releaseIdNoDep ); System.out.println("done in " + (System.nanoTime() - start)); ReleaseId dep1 = ks.newReleaseId( "org.slf4j", "slf4j-api", "1.7.2" ); ReleaseId dep2 = ks.newReleaseId( "com.google.gwt", "gwt-user", "2.7.0" ); ReleaseId dep3 = ks.newReleaseId( "org.hibernate", "hibernate-validator", "4.1.0.Final" ); start = System.nanoTime(); InternalKieModule kJar2 = createKieJarWithDependencies( ks, releaseIdWithDep, false, "rule1", dep1, dep2, dep3); KieContainer kieContainer2 = ks.newKieContainer( releaseIdWithDep ); System.out.println("done in " + (System.nanoTime() - start)); } @Test public void testKieScannerScopesNotRequired() throws Exception { MavenRepository repository = getMavenRepository(); KieServices ks = KieServices.Factory.get(); ReleaseId releaseIdWithDep = ks.newReleaseId( "org.kie", "test-with-dep", "1.0-SNAPSHOT" ); Dependency dep1 = dependencyWithScope( "org.kie", "test-dep1-in-test-scope" , "1.0-SNAPSHOT", "test" ); Dependency dep2 = dependencyWithScope( "org.kie", "test-dep2-in-provided-scope", "1.0-SNAPSHOT", "provided" ); Dependency dep3 = dependencyWithScope( "org.kie", "test-dep3-in-system-scope" , "1.0-SNAPSHOT", "system" ); dep3.setSystemPath(fileManager.getRootDirectory().getAbsolutePath()); // to ensure KieBuilder is able to build correctly: repository.installArtifact(ks.newReleaseId("org.kie", "test-dep3-in-system-scope", "1.0-SNAPSHOT"), new byte[]{}, new byte[]{}); InternalKieModule kJar2 = createKieJarWithDependencies( ks, releaseIdWithDep, false, "rule1", dep1, dep2, dep3); KieContainer kieContainer = ks.newKieContainer( releaseIdWithDep ); // DROOLS-1051 following should not throw NPE because dependencies are not in scope of scanner KieScanner scanner = ks.newKieScanner(kieContainer); assertNotNull(scanner); } @Test public void testKScannerStartNotDeployed() throws Exception { // BZ-1200784 KieServices ks = KieServices.Factory.get(); ReleaseId releaseId = ks.newReleaseId("org.kie", "scanner-start-not-deployed-test", "1.0-SNAPSHOT"); InternalKieModule kJar1 = createKieJar(ks, releaseId, "rule1", "rule2"); KieContainer kieContainer = ks.newKieContainer(releaseId); // starting KieScanner KieScanner scanner = ks.newKieScanner(kieContainer); // scan the maven repo to get the new kjar version before it is deployed into Maven repo // should not throw NPE because of uninitialized dependencies due to parsing parent pom failure scanner.scanNow(); MavenRepository repository = getMavenRepository(); repository.installArtifact(releaseId, kJar1, createKPom(fileManager, releaseId)); // create a ksesion and check it works as expected KieSession ksession = kieContainer.newKieSession("KSession1"); checkKSession(ksession, "rule1", "rule2"); } @Test public void testKScannerWithRange() throws Exception { KieServices ks = KieServices.Factory.get(); ReleaseId releaseId1 = ks.newReleaseId("org.kie", "scanner-range-test", "1.0.1"); ReleaseId releaseId2 = ks.newReleaseId("org.kie", "scanner-range-test", "1.0.2"); ReleaseId releaseRange = ks.newReleaseId("org.kie", "scanner-range-test", "[1.0.0,)"); InternalKieModule kJar1 = createKieJar(ks, releaseId1, "rule1", "rule2"); KieContainer kieContainer = ks.newKieContainer(releaseRange); MavenRepository repository = getMavenRepository(); repository.installArtifact(releaseId1, kJar1, createKPom(fileManager, releaseId1)); // create a ksesion and check it works as expected KieSession ksession = kieContainer.newKieSession("KSession1"); checkKSession(ksession, "rule1", "rule2"); // create a new kjar InternalKieModule kJar2 = createKieJar(ks, releaseId2, "rule2", "rule3"); // deploy it on maven repository.installArtifact(releaseId2, kJar2, createKPom(fileManager, releaseId2)); // since I am not calling start() on the scanner it means it won't have automatic scheduled scanning InternalKieScanner scanner = (InternalKieScanner) ks.newKieScanner(kieContainer); assertEquals(releaseId1, scanner.getCurrentReleaseId()); assertEquals(InternalKieScanner.Status.STOPPED, scanner.getStatus()); // scan the maven repo to get the new kjar version and deploy it on the kcontainer scanner.scanNow(); assertEquals(releaseId2, scanner.getCurrentReleaseId()); assertEquals(InternalKieScanner.Status.STOPPED, scanner.getStatus()); // create a ksesion and check it works as expected KieSession ksession2 = kieContainer.newKieSession("KSession1"); checkKSession(ksession2, "rule2", "rule3"); ks.getRepository().removeKieModule(releaseId1); ks.getRepository().removeKieModule(releaseId2); } @Test public void testKScannerWithRange_withListener() throws Exception { KieServices ks = KieServices.Factory.get(); MavenRepository repository = getMavenRepository(); String artifactId = "scanner-range-test-withlistener"; ReleaseId releaseId1 = ks.newReleaseId("org.kie", artifactId, "1.0.1"); ReleaseId releaseId2 = ks.newReleaseId("org.kie", artifactId, "1.0.2"); // Because KieScanner also check the local repo, ensure the artifact are not deployed on the local maven repo repository.removeLocalArtifact( releaseId1 ); repository.removeLocalArtifact( releaseId2 ); ReleaseId releaseRange = ks.newReleaseId("org.kie", artifactId, "[1.0.0,)"); InternalKieModule kJar1 = createKieJar(ks, releaseId1, "rule1", "rule2"); KieContainer kieContainer = ks.newKieContainer(releaseRange); List<KieScannerEvent> events = new ArrayList<>(); InternalKieScanner scanner = (KieRepositoryScannerImpl) ks.newKieScanner(kieContainer); KieScannerEventListener listener = new KieScannerEventListener() { public void onKieScannerStatusChangeEvent(KieScannerStatusChangeEvent statusChange) { LOG.info("KieScanner event: {}", statusChange); events.add(statusChange); } public void onKieScannerUpdateResultsEvent(KieScannerUpdateResultsEvent updtaeResults) { LOG.info("KieScanner event: {}", updtaeResults); events.add(updtaeResults); } }; scanner.addListener( listener ); scanner.scanNow(); // Because 1.0.2 does not exist, will perform a scan but will NOT update. assertThat( events, CoreMatchers.hasItem( new KieScannerStatusChangeEventImpl(KieScanner.Status.SCANNING) ) ); assertThat( events, CoreMatchers.not( CoreMatchers.hasItem( new KieScannerStatusChangeEventImpl(KieScanner.Status.UPDATING) )) ); events.clear(); repository.installArtifact(releaseId1, kJar1, createKPom(fileManager, releaseId1)); KieSession ksession = kieContainer.newKieSession("KSession1"); checkKSession(ksession, "rule1", "rule2"); // create a new kjar InternalKieModule kJar2 = createKieJar(ks, releaseId2, "rule2", "rule3"); // deploy it on maven repository.installArtifact(releaseId2, kJar2, createKPom(fileManager, releaseId2)); // since I am not calling start() on the scanner it means it won't have automatic scheduled scanning assertEquals(releaseId1, scanner.getCurrentReleaseId()); assertEquals(InternalKieScanner.Status.STOPPED, scanner.getStatus()); // scan the maven repo to get the new kjar version and deploy it on the kcontainer scanner.scanNow(); assertEquals(releaseId2, scanner.getCurrentReleaseId()); assertEquals(InternalKieScanner.Status.STOPPED, scanner.getStatus()); // create a ksesion and check it works as expected KieSession ksession2 = kieContainer.newKieSession("KSession1"); checkKSession(ksession2, "rule2", "rule3"); assertThat( events, CoreMatchers.hasItem( new KieScannerStatusChangeEventImpl(KieScanner.Status.SCANNING) ) ); assertThat( events, CoreMatchers.hasItem( new KieScannerStatusChangeEventImpl(KieScanner.Status.UPDATING) ) ); assertTrue( events.get(2) instanceof KieScannerUpdateResultsEventImpl ); assertFalse( ((KieScannerUpdateResultsEventImpl)events.get(2)).getResults().hasMessages(Message.Level.ERROR) ); events.clear(); ks.getRepository().removeKieModule(releaseId1); ks.getRepository().removeKieModule(releaseId2); scanner.removeListener( listener ); assertEquals( 0, scanner.getListeners().size() ); repository.removeLocalArtifact( releaseId1 ); repository.removeLocalArtifact( releaseId2 ); } @Test public void testKScannerWithRange_withListener_errors() throws Exception { KieServices ks = KieServices.Factory.get(); MavenRepository repository = getMavenRepository(); String artifactId = "scanner-range-test-withlistener-errors"; ReleaseId releaseId1 = ks.newReleaseId("org.kie", artifactId, "1.0.1"); ReleaseId releaseId2 = ks.newReleaseId("org.kie", artifactId, "1.0.2"); // Because KieScanner also check the local repo, ensure the artifact are not deployed on the local maven repo repository.removeLocalArtifact( releaseId1 ); repository.removeLocalArtifact( releaseId2 ); ReleaseId releaseRange = ks.newReleaseId("org.kie", artifactId, "[1.0.0,)"); InternalKieModule kJar1 = createKieJar(ks, releaseId1, "rule1", "rule2"); KieContainer kieContainer = ks.newKieContainer(releaseRange); List<KieScannerEvent> events = new ArrayList<>(); InternalKieScanner scanner = (KieRepositoryScannerImpl) ks.newKieScanner(kieContainer); KieScannerEventListener listener = new KieScannerEventListener() { public void onKieScannerStatusChangeEvent(KieScannerStatusChangeEvent statusChange) { LOG.info("KieScanner event: {}", statusChange); events.add(statusChange); } public void onKieScannerUpdateResultsEvent(KieScannerUpdateResultsEvent updtaeResults) { LOG.info("KieScanner event: {}", updtaeResults); events.add(updtaeResults); } }; scanner.addListener( listener ); scanner.scanNow(); // Because 1.0.2 does not exist, will perform a scan but will NOT update. assertThat( events, CoreMatchers.hasItem( new KieScannerStatusChangeEventImpl(KieScanner.Status.SCANNING) ) ); assertThat( events, CoreMatchers.not( CoreMatchers.hasItem( new KieScannerStatusChangeEventImpl(KieScanner.Status.UPDATING) )) ); events.clear(); repository.installArtifact(releaseId1, kJar1, createKPom(fileManager, releaseId1)); KieSession ksession = kieContainer.newKieSession("KSession1"); checkKSession(ksession, "rule1", "rule2"); // Create a wrong KJAR for releaseId2 KieFileSystem kfs = ks.newKieFileSystem(); String pomContent = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" + " xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n" + " <modelVersion>4.0.0</modelVersion>\n" + "\n" + " <groupId>" + releaseId2.getGroupId() + "</groupId>\n" + " <artifactId>" + releaseId2.getArtifactId() + "</artifactId>\n" + " <version>" + releaseId2.getVersion() + "</version></project>\n"; kfs.writePomXML(pomContent); kfs.write("rulebroken" + ".drl", "rule X when asd asd then end" ); kfs.write("META-INF/kmodule.xml", "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<kmodule xmlns=\"http://www.drools.org/xsd/kmodule\">\n" + " <!-- This is a minimal kmodule.xml. Ref Drools documentation, see http://docs.jboss.org/drools/release/6.1.0.Final/drools-docs/html_single/index.html#d0e1112 -->\n" + "</kmodule>\n"); File tempJar = File.createTempFile("org.kie"+artifactId+"1.0.2", "tmp"); LOG.info("Writing to temp file: {}", tempJar); // please notice that writeAsJar would return a new file with .jar postfixed tempJar = ((KieFileSystemImpl)kfs).asMemoryFileSystem().writeAsJar(tempJar.getParentFile(), tempJar.getName()); File tempPom = File.createTempFile("org.kie"+artifactId+"1.0.2", "tmp.xml"); LOG.info("Writing to temp file: {}", tempPom); FileUtils.writeStringToFile(tempPom, pomContent, "UTF-8"); repository.installArtifact(releaseId2, tempJar, tempPom); assertEquals(releaseId1, scanner.getCurrentReleaseId()); assertEquals(InternalKieScanner.Status.STOPPED, scanner.getStatus()); // scan the maven repo to get the new kjar version and deploy it on the kcontainer scanner.scanNow(); // Keeping at previous release assertEquals(releaseId1, scanner.getCurrentReleaseId()); assertEquals(InternalKieScanner.Status.STOPPED, scanner.getStatus()); // there should be no update performed. assertThat( events, CoreMatchers.hasItem( new KieScannerStatusChangeEventImpl(KieScanner.Status.SCANNING) ) ); assertThat( events, CoreMatchers.hasItem( new KieScannerStatusChangeEventImpl(KieScanner.Status.UPDATING) ) ); assertTrue( events.get(2) instanceof KieScannerUpdateResultsEventImpl ); assertTrue( ((KieScannerUpdateResultsEventImpl)events.get(2)).getResults().hasMessages(Message.Level.ERROR) ); events.clear(); ks.getRepository().removeKieModule(releaseId1); ks.getRepository().removeKieModule(releaseId2); scanner.removeListener( listener ); assertEquals( 0, scanner.getListeners().size() ); repository.removeLocalArtifact( releaseId1 ); repository.removeLocalArtifact( releaseId2 ); } @Test public void testKScannerWithKJarContainingClasses() throws Exception { testKScannerWithType(false); } @Test public void testKScannerWithKJarContainingTypeDeclaration() throws Exception { testKScannerWithType(true); } private void testKScannerWithType(boolean useTypeDeclaration) throws Exception { KieServices ks = KieServices.Factory.get(); ReleaseId releaseId = ks.newReleaseId("org.kie", "scanner-test", "1.0-SNAPSHOT"); InternalKieModule kJar1 = createKieJarWithClass(ks, releaseId, useTypeDeclaration, 2, 7); MavenRepository repository = getMavenRepository(); repository.installArtifact(releaseId, kJar1, createKPom(fileManager, releaseId)); KieContainer kieContainer = ks.newKieContainer(releaseId); KieScanner scanner = ks.newKieScanner(kieContainer); KieSession ksession = kieContainer.newKieSession("KSession1"); checkKSession(ksession, 14); InternalKieModule kJar2 = createKieJarWithClass(ks, releaseId, useTypeDeclaration, 3, 5); repository.installArtifact(releaseId, kJar2, createKPom(fileManager, releaseId)); scanner.scanNow(); KieSession ksession2 = kieContainer.newKieSession("KSession1"); checkKSession(ksession2, 15); ks.getRepository().removeKieModule(releaseId); } @Test public void testKScannerWithFunction() throws Exception { String drl1 = "global java.util.List list;\n" + "\n" + "function boolean doSomething(String name) {\n" + " return true ;\n" + "}\n" + " \n" + "rule R1 when\n" + " $s : String( )\n" + " eval(doSomething($s))\n" + "then\n" + " list.add(\"XXX:\" + $s);\n" + "end"; String drl2 = "global java.util.List list;\n" + "\n" + "function boolean doSomething(String name) {\n" + " return true ;\n" + "}\n" + " \n" + "rule R1 when\n" + " $s : String( )\n" + " eval(doSomething($s))\n" + "then\n" + " list.add(\"YYY:\" + $s);\n" + "end"; checkUpdateDRLInSameSession(drl1, drl2); } @Test public void testKScannerWithNewFunction() throws Exception { String drl1 = "global java.util.List list;\n" + "\n" + " \n" + "rule R1 when\n" + " $s : String( )\n" + "then\n" + " list.add(\"XXX:\" + $s);\n" + "end"; String drl2 = "global java.util.List list;\n" + "\n" + "function boolean doSomething(String name) {\n" + " return true ;\n" + "}\n" + " \n" + "rule R1 when\n" + " $s : String( )\n" + " eval(doSomething($s))\n" + "then\n" + " list.add(\"YYY:\" + $s);\n" + "end"; checkUpdateDRLInSameSession(drl1, drl2); } private void checkUpdateDRLInSameSession(String drl1, String drl2) throws IOException { KieServices ks = KieServices.Factory.get(); ReleaseId releaseId = ks.newReleaseId("org.kie", "scanner-test", "1.0-SNAPSHOT"); InternalKieModule kJar1 = createKieJarFromDrl(ks, releaseId, drl1); MavenRepository repository = getMavenRepository(); repository.installArtifact(releaseId, kJar1, createKPom(fileManager, releaseId)); KieContainer kieContainer = ks.newKieContainer(releaseId); KieScanner scanner = ks.newKieScanner(kieContainer); KieSession ksession = kieContainer.newKieSession("KSession1"); List<String> list = new ArrayList<String>(); ksession.setGlobal( "list", list ); ksession.insert("111"); ksession.fireAllRules(); assertEquals(1, list.size()); assertEquals("XXX:111", list.get(0)); list.clear(); InternalKieModule kJar2 = createKieJarFromDrl(ks, releaseId, drl2); repository.installArtifact(releaseId, kJar2, createKPom(fileManager, releaseId)); scanner.scanNow(); ksession.insert("222"); ksession.fireAllRules(); assertEquals(2, list.size()); assertTrue(list.containsAll(asList("YYY:111", "YYY:222"))); ks.getRepository().removeKieModule(releaseId); } private InternalKieModule createKieJarFromDrl(KieServices ks, ReleaseId releaseId, String drl) throws IOException { KieFileSystem kfs = createKieFileSystemWithKProject(ks, false); kfs.writePomXML(getPom(releaseId)); kfs.write("src/main/resources/KBase1/rule1.drl", drl); KieBuilder kieBuilder = ks.newKieBuilder(kfs); assertTrue(kieBuilder.buildAll().getResults().getMessages().isEmpty()); return (InternalKieModule) kieBuilder.getKieModule(); } @Test public void testLoadKieJarFromMavenRepo() throws Exception { KieServices ks = KieServices.Factory.get(); ReleaseId releaseId = ks.newReleaseId("org.kie", "scanner-test", "1.0-SNAPSHOT"); final String drl = " global java.util.List list; \n" + " rule R1 \n" + " when \n" + " not(String()) \n" + " then \n" + " list.add(15);\n" + " end "; InternalKieModule kJar1 = createKieJarFromDrl(ks, releaseId, drl); MavenRepository repository = getMavenRepository(); repository.installArtifact(releaseId, kJar1, createKPom(fileManager, releaseId)); KieContainer kieContainer = ks.newKieContainer(releaseId); KieSession ksession2 = kieContainer.newKieSession("KSession1"); checkKSession(ksession2, 15); ks.getRepository().removeKieModule(releaseId); } @Test public void testScannerOnPomProject() throws Exception { KieServices ks = KieServices.Factory.get(); ReleaseId releaseId1 = ks.newReleaseId("org.kie", "scanner-test", "1.0"); ReleaseId releaseId2 = ks.newReleaseId("org.kie", "scanner-test", "2.0"); MavenRepository repository = getMavenRepository(); repository.deployPomArtifact("org.kie", "scanner-master-test", "1.0", createMasterKPom("scanner-test")); resetFileManager(); InternalKieModule kJar1 = createKieJarWithClass(ks, releaseId1, false, 2, 7); repository.installArtifact(releaseId1, kJar1, createKPom(fileManager, releaseId1)); KieContainer kieContainer = ks.newKieContainer(ks.newReleaseId("org.kie", "scanner-master-test", "LATEST")); KieSession ksession = kieContainer.newKieSession("KSession1"); checkKSession(ksession, 14); KieScanner scanner = ks.newKieScanner(kieContainer); InternalKieModule kJar2 = createKieJarWithClass(ks, releaseId2, false, 3, 5); repository.installArtifact(releaseId2, kJar2, createKPom(fileManager, releaseId1)); scanner.scanNow(); KieSession ksession2 = kieContainer.newKieSession("KSession1"); checkKSession(ksession2, 15); ks.getRepository().removeKieModule(releaseId1); ks.getRepository().removeKieModule(releaseId2); } @Test public void testScannerOnPomProjectWithFixedVersion() throws Exception { KieServices ks = KieServices.Factory.get(); ReleaseId releaseId1 = ks.newReleaseId("org.kie", "scanner-test", "1.0"); ReleaseId releaseId2 = ks.newReleaseId("org.kie", "scanner-test", "2.0"); MavenRepository repository = getMavenRepository(); repository.deployPomArtifact("org.kie", "scanner-master-test", "1.0", createMasterKPom("scanner-test", "1.0")); resetFileManager(); InternalKieModule kJar1 = createKieJarWithClass(ks, releaseId1, false, 2, 7); repository.installArtifact(releaseId1, kJar1, createKPom(fileManager, releaseId1)); KieContainer kieContainer = ks.newKieContainer(ks.newReleaseId("org.kie", "scanner-master-test", "LATEST")); KieSession ksession = kieContainer.newKieSession("KSession1"); checkKSession(ksession, 14); KieScanner scanner = ks.newKieScanner(kieContainer); repository.deployPomArtifact("org.kie", "scanner-master-test", "2.0", createMasterKPom("scanner-test", "2.0")); InternalKieModule kJar2 = createKieJarWithClass(ks, releaseId2, false, 3, 5); repository.installArtifact(releaseId2, kJar2, createKPom(fileManager, releaseId1)); scanner.scanNow(); KieSession ksession2 = kieContainer.newKieSession("KSession1"); checkKSession(ksession2, 15); ks.getRepository().removeKieModule(releaseId1); ks.getRepository().removeKieModule(releaseId2); } @Test public void testScannerOnPomProjectSameKieSession() throws Exception { KieServices ks = KieServices.Factory.get(); ReleaseId releaseId1 = ks.newReleaseId("org.kie", "scanner-test", "1.0"); ReleaseId releaseId2 = ks.newReleaseId("org.kie", "scanner-test", "2.0"); MavenRepository repository = getMavenRepository(); repository.deployPomArtifact("org.kie", "scanner-master-test", "1.0", createMasterKPom("scanner-test", "1.0")); resetFileManager(); InternalKieModule kJar1 = createKieJarWithClass(ks, releaseId1, true, 2, 7); repository.installArtifact(releaseId1, kJar1, createKPom(fileManager, releaseId1)); KieContainer kieContainer = ks.newKieContainer(ks.newReleaseId("org.kie", "scanner-master-test", "LATEST")); KieSession ksession = kieContainer.newKieSession("KSession1"); checkKSession(false, ksession, 14); KieScanner scanner = ks.newKieScanner(kieContainer); repository.deployPomArtifact("org.kie", "scanner-master-test", "2.0", createMasterKPom("scanner-test", "2.0")); InternalKieModule kJar2 = createKieJarWithClass(ks, releaseId2, true, 3, 5); repository.installArtifact(releaseId2, kJar2, createKPom(fileManager, releaseId1)); scanner.scanNow(); checkKSession(ksession, 10, 15); ks.getRepository().removeKieModule(releaseId1); ks.getRepository().removeKieModule(releaseId2); } private File createMasterKPom(String depArtifactId) throws IOException { return createMasterKPom(depArtifactId, "LATEST"); } private File createMasterKPom(String depArtifactId, String depVersion) throws IOException { String pom = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" + " xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n" + " <modelVersion>4.0.0</modelVersion>\n" + "\n" + " <groupId>org.kie</groupId>\n" + " <artifactId>scanner-master-test</artifactId>\n" + " <version>1.0</version>\n" + " <packaging>pom</packaging>\n" + "\n" + " <dependencies>\n" + " <dependency>\n" + " <groupId>org.kie</groupId>\n" + " <artifactId>" + depArtifactId + "</artifactId>\n" + " <version>" + depVersion + "</version>\n" + " </dependency>\n" + " </dependencies>\n" + "</project>"; File pomFile = fileManager.newFile("pom.xml"); fileManager.write(pomFile, pom); return pomFile; } @Test public void testKieScannerOnClasspathContainerMustFail() { KieServices ks = KieServices.Factory.get(); KieContainer kieContainer = ks.getKieClasspathContainer(); try { KieScanner scanner = ks.newKieScanner(kieContainer); fail("Creating a KieScanner from a KieClasspathContainer must fail"); } catch (RuntimeException e) { } } @Test public void testTypeAndRuleInDifferentKieModules() throws Exception { KieServices ks = KieServices.Factory.get(); ReleaseId depId = ks.newReleaseId("org.kie", "test-types", "1.0"); InternalKieModule kJar1 = createKieJarWithType(ks, depId); MavenRepository repository = getMavenRepository(); repository.installArtifact(depId, kJar1, createKPom(fileManager, depId)); ReleaseId releaseId = ks.newReleaseId("org.kie", "test-rules", "1.0"); InternalKieModule kieModule = createKieJarWithRules(ks, releaseId, depId); KieContainer kieContainer = ks.newKieContainer(releaseId); KieSession ksession = kieContainer.newKieSession("KSession1"); checkKSession(ksession, 15); } private InternalKieModule createKieJarWithType(KieServices ks, ReleaseId releaseId) throws IOException { KieFileSystem kfs = createKieFileSystemWithKProject(ks); kfs.write("src/main/resources/KBase1/r1.drl", "package org.kie.test\n" + getDRLWithType()); kfs.writePomXML( getPom(releaseId) ); KieBuilder kieBuilder = ks.newKieBuilder(kfs); assertTrue(kieBuilder.buildAll().getResults().getMessages().isEmpty()); return ( InternalKieModule ) kieBuilder.getKieModule(); } private InternalKieModule createKieJarWithRules(KieServices ks, ReleaseId releaseId, ReleaseId depId) throws IOException { KieFileSystem kfs = createKieFileSystemWithKProject(ks); kfs.write("src/main/resources/KBase1/r1.drl", "package org.kie.test\n" + getDRLWithRules(3, 5)); kfs.writePomXML( getPom(releaseId, depId) ); KieBuilder kieBuilder = ks.newKieBuilder(kfs); kieBuilder.buildAll(); assertTrue(kieBuilder.getResults().getMessages().isEmpty()); return ( InternalKieModule ) kieBuilder.getKieModule(); } @Test public void testScannerOnPomRuleProject() throws Exception { KieServices ks = KieServices.Factory.get(); ReleaseId releaseId1 = ks.newReleaseId("org.kie", "scanner-test", "1.0"); ReleaseId releaseId2 = ks.newReleaseId("org.kie", "scanner-test", "2.0"); MavenRepository repository = getMavenRepository(); repository.deployPomArtifact("org.kie", "scanner-master-test", "1.0", createMasterKPom("scanner-test")); resetFileManager(); InternalKieModule kJar1 = createKieJar(ks, releaseId1, "rule1"); repository.installArtifact(releaseId1, kJar1, createKPom(fileManager, releaseId1)); KieContainer kieContainer = ks.newKieContainer(ks.newReleaseId("org.kie", "scanner-master-test", "LATEST")); KieSession ksession = kieContainer.newKieSession("KSession1"); checkKSession(ksession, "rule1"); KieScanner scanner = ks.newKieScanner(kieContainer); InternalKieModule kJar2 = createKieJar(ks, releaseId2, "rule2"); repository.installArtifact(releaseId2, kJar2, createKPom(fileManager, releaseId2)); scanner.scanNow(); KieSession ksession2 = kieContainer.newKieSession("KSession1"); checkKSession(ksession2, "rule2"); ks.getRepository().removeKieModule(releaseId1); ks.getRepository().removeKieModule(releaseId2); } @Test public void testMissingDependency() throws Exception { KieServices ks = KieServices.Factory.get(); MavenRepository repository = getMavenRepository(); ReleaseId releaseId = ks.newReleaseId("org.kie", "scanner-test", "1.0"); ReleaseId missingDep = ks.newReleaseId("org.kie", "missing-dep", "1.0"); KieFileSystem kfs = createKieFileSystemWithKProject(ks, false); kfs.writePomXML(getPom(releaseId, missingDep)); kfs.write("src/main/resources/KBase1/rule1.drl", createDRLWithTypeDeclaration(1, 1)); KieBuilder kieBuilder = ks.newKieBuilder(kfs); List<Message> messages = kieBuilder.buildAll().getResults().getMessages(); assertEquals(1, messages.size()); assertTrue(messages.get(0).toString().contains("missing-dep")); ks.getRepository().removeKieModule(releaseId); } @Test public void testScanIncludedDependency() throws Exception { MavenRepository repository = getMavenRepository(); KieServices ks = KieServices.Factory.get(); ReleaseId containerReleaseId = KieServices.Factory.get().newReleaseId( "org.kie", "test-container", "1.0.0-SNAPSHOT" ); ReleaseId includedReleaseId = KieServices.Factory.get().newReleaseId( "org.kie", "test-project", "1.0.0-SNAPSHOT" ); InternalKieModule kJar1 = createKieJar(ks, includedReleaseId, "rule1"); repository.installArtifact(includedReleaseId, kJar1, createKPom(fileManager, includedReleaseId)); resetFileManager(); KieFileSystem kfs = ks.newKieFileSystem(); KieModuleModel kproj = ks.newKieModuleModel(); kproj.newKieBaseModel("KBase2").addInclude("KBase1").newKieSessionModel("KSession2"); kfs.writeKModuleXML(kproj.toXML()); kfs.writePomXML(getPom(containerReleaseId, includedReleaseId)); KieBuilder kieBuilder = ks.newKieBuilder(kfs); assertTrue(kieBuilder.buildAll().getResults().getMessages().isEmpty()); InternalKieModule containerKJar = (InternalKieModule) kieBuilder.getKieModule(); repository.installArtifact(containerReleaseId, containerKJar, createKPom(fileManager, containerReleaseId, includedReleaseId)); KieContainer kieContainer = ks.newKieContainer(containerReleaseId); KieSession ksession = kieContainer.newKieSession("KSession2"); checkKSession(ksession, "rule1"); KieScanner scanner = ks.newKieScanner(kieContainer); InternalKieModule kJar2 = createKieJar(ks, includedReleaseId, "rule2"); repository.installArtifact(includedReleaseId, kJar2, createKPom(fileManager, includedReleaseId)); scanner.scanNow(); KieSession ksession2 = kieContainer.newKieSession("KSession2"); checkKSession(ksession2, "rule2"); ks.getRepository().removeKieModule(containerReleaseId); ks.getRepository().removeKieModule(includedReleaseId); } @Test @Ignore public void testScanIncludedAndIncludingDependency() throws Exception { MavenRepository repository = getMavenRepository(); KieServices ks = KieServices.Factory.get(); ReleaseId containerReleaseId = KieServices.Factory.get().newReleaseId( "org.kie", "test-container", "1.0.0-SNAPSHOT" ); ReleaseId includedReleaseId = KieServices.Factory.get().newReleaseId( "org.kie", "test-project", "1.0.0-SNAPSHOT" ); InternalKieModule kJar1 = createKieJar(ks, includedReleaseId, "rule1"); repository.installArtifact(includedReleaseId, kJar1, createKPom(fileManager, includedReleaseId)); resetFileManager(); InternalKieModule containerKJar = createIncludingKJar(containerReleaseId, includedReleaseId, "ruleX"); repository.installArtifact(containerReleaseId, containerKJar, createKPom(fileManager, containerReleaseId, includedReleaseId)); KieContainer kieContainer = ks.newKieContainer(containerReleaseId); KieSession ksession = kieContainer.newKieSession("KSession2"); checkKSession(ksession, "rule1", "ruleX"); resetFileManager(); KieScanner scanner = ks.newKieScanner(kieContainer); InternalKieModule kJar2 = createKieJar(ks, includedReleaseId, "rule2"); repository.installArtifact(includedReleaseId, kJar2, createKPom(fileManager, includedReleaseId)); resetFileManager(); InternalKieModule containerKJar2 = createIncludingKJar(containerReleaseId, includedReleaseId, "ruleY"); repository.installArtifact(containerReleaseId, containerKJar2, createKPom(fileManager, containerReleaseId, includedReleaseId)); resetFileManager(); scanner.scanNow(); KieSession ksession2 = kieContainer.newKieSession("KSession2"); checkKSession(ksession2, "rule2", "ruleY"); ks.getRepository().removeKieModule(containerReleaseId); ks.getRepository().removeKieModule(includedReleaseId); } private InternalKieModule createIncludingKJar(ReleaseId containerReleaseId, ReleaseId includedReleaseId, String rule) { KieServices ks = KieServices.Factory.get(); KieFileSystem kfs = ks.newKieFileSystem(); String file = "org/test/" + rule + ".drl"; kfs.write("src/main/resources/KBase2/" + file, createDRL(rule)); KieModuleModel kproj = ks.newKieModuleModel(); kproj.newKieBaseModel("KBase2").addInclude("KBase1").newKieSessionModel("KSession2"); kfs.writeKModuleXML(kproj.toXML()); kfs.writePomXML(getPom(containerReleaseId, includedReleaseId)); KieBuilder kieBuilder = ks.newKieBuilder(kfs); assertTrue(kieBuilder.buildAll().getResults().getMessages().isEmpty()); return (InternalKieModule) kieBuilder.getKieModule(); } @Test public void testKScannerWithGDRL() throws Exception { // BZ-1310261 String rule1 = "import java.util.List;\n" + "rule R when\n" + " $s : String()\n" + "then\n" + " list.add(\"Hello \" + $s);\n" + "end"; String rule2 = "import java.util.List;\n" + "rule R when\n" + " $s : String()\n" + "then\n" + " list.add(\"Hi \" + $s);\n" + "end"; KieServices ks = KieServices.Factory.get(); ReleaseId releaseId = ks.newReleaseId("org.kie", "scanner-test", "1.0-SNAPSHOT"); InternalKieModule kJar1 = createKieJarWithGDRL(ks, releaseId, rule1); KieContainer kieContainer = ks.newKieContainer(releaseId); MavenRepository repository = getMavenRepository(); repository.installArtifact(releaseId, kJar1, createKPom(fileManager, releaseId)); // create a ksesion and check it works as expected KieSession ksession = kieContainer.newKieSession("KSession1"); List<String> list = new ArrayList<String>(); ksession.setGlobal( "list", list ); ksession.insert( "Mario" ); ksession.fireAllRules(); assertEquals( 1, list.size() ); assertEquals( "Hello Mario", list.get(0) ); list.clear(); ksession.dispose(); // create a new kjar InternalKieModule kJar2 = createKieJarWithGDRL(ks, releaseId, rule2); // deploy it on maven repository.installArtifact(releaseId, kJar2, createKPom(fileManager, releaseId)); // since I am not calling start() on the scanner it means it won't have automatic scheduled scanning KieScanner scanner = ks.newKieScanner(kieContainer); // scan the maven repo to get the new kjar version and deploy it on the kcontainer scanner.scanNow(); // create a ksesion and check it works as expected // create a ksesion and check it works as expected ksession = kieContainer.newKieSession("KSession1"); list = new ArrayList<String>(); ksession.setGlobal( "list", list ); ksession.insert( "Mario" ); ksession.fireAllRules(); assertEquals( 1, list.size() ); assertEquals( "Hi Mario", list.get(0) ); list.clear(); ksession.dispose(); ks.getRepository().removeKieModule(releaseId); } private InternalKieModule createKieJarWithGDRL(KieServices ks, ReleaseId releaseId, String rule) throws IOException { KieFileSystem kfs = createKieFileSystemWithKProject(ks, false); kfs.writePomXML(getPom(releaseId)); kfs.write("src/main/resources/rule.drl", rule); kfs.write("src/main/resources/global.gdrl", "global java.util.List list;"); KieBuilder kieBuilder = ks.newKieBuilder(kfs); assertTrue(kieBuilder.buildAll().getResults().getMessages().isEmpty()); return (InternalKieModule) kieBuilder.getKieModule(); } @Test public void testKJarContainingClassLoadedFromClassLoaderSameKBase() throws Exception { testKScannerWithKJarContainingClassLoadedFromClassLoader(false); } @Test public void testKJarContainingClassLoadedFromClassLoaderDifferentKBase() throws Exception { testKScannerWithKJarContainingClassLoadedFromClassLoader(true); } @Test public void testKScannerStartScanNow() throws Exception { KieServices ks = KieServices.Factory.get(); ReleaseId releaseId = ks.newReleaseId("org.kie", "scanner-test", "1.0-SNAPSHOT"); InternalKieModule kJar1 = createKieJar(ks, releaseId, "rule1", "rule2"); KieContainer kieContainer = ks.newKieContainer(releaseId); MavenRepository repository = getMavenRepository(); repository.installArtifact(releaseId, kJar1, createKPom(fileManager, releaseId)); // create a ksesion and check it works as expected KieSession ksession = kieContainer.newKieSession("KSession1"); checkKSession(ksession, "rule1", "rule2"); KieScanner scanner = ks.newKieScanner(kieContainer); // Starting scanner with 200ms interval. scanner.start(100); try { // Manual scan, should continue interval scanning afterwards. scanner.scanNow(); InternalKieModule kJar2 = createKieJar(ks, releaseId, "rule2", "rule3"); repository.installArtifact(releaseId, kJar2, createKPom(fileManager, releaseId)); // Check each 100ms until scanner finds the new kjar (or timeout is reached) long timeSpent = 0; while (timeSpent <= 5000) { // create a ksession and check the ksession produces the expected results KieSession ksession2 = kieContainer.newKieSession("KSession1"); if (producesResults(ksession2, "rule2", "rule3")) { break; } Thread.sleep(100); timeSpent += 100; } } finally { scanner.stop(); ks.getRepository().removeKieModule(releaseId); } } private void testKScannerWithKJarContainingClassLoadedFromClassLoader(boolean differentKbases) throws Exception { // DROOLS-1231 KieServices ks = KieServices.Factory.get(); ReleaseId releaseId = ks.newReleaseId("org.kie", "scanner-test", "1.0-SNAPSHOT"); InternalKieModule kJar1 = createKieJarWithJavaClass(ks, releaseId, "KBase1", 7); MavenRepository repository = getMavenRepository(); repository.installArtifact(releaseId, kJar1, createKPom(fileManager, releaseId)); ks.getRepository().removeKieModule(releaseId); KieContainer kieContainer = ks.newKieContainer(releaseId); KieScanner scanner = ks.newKieScanner(kieContainer); Class<?> beanClass = kieContainer.getClassLoader().loadClass( "org.kie.test.Bean" ); KieSession ksession = kieContainer.newKieSession("KSession1"); Object bean = beanClass.getDeclaredConstructors()[0].newInstance( 2 ); ksession.insert( bean ); checkKSession(ksession, 14); InternalKieModule kJar2 = createKieJarWithJavaClass(ks, releaseId, differentKbases ? "KBase2" : "KBase1", 5); repository.installArtifact(releaseId, kJar2, createKPom(fileManager, releaseId)); ks.getRepository().removeKieModule(releaseId); // forces cache of old Bean class definition before updating to newer release Class<?> beanClass1 = Class.forName( "org.kie.test.Bean", true, kieContainer.getClassLoader() ); kieContainer.updateToVersion( releaseId ); beanClass = kieContainer.getClassLoader().loadClass( "org.kie.test.Bean" ); KieSession ksession2 = kieContainer.newKieSession("KSession1"); bean = beanClass.getDeclaredConstructors()[0].newInstance( 3 ); ksession2.insert( bean ); checkKSession(ksession2, 15); ks.getRepository().removeKieModule(releaseId); } private InternalKieModule createKieJarWithJavaClass(KieServices ks, ReleaseId releaseId, String kbaseName, int factor) throws IOException { String drl = "package org.kie.test.drl\n" + "import org.kie.test.Bean\n" + "global java.util.List list\n" + "rule R1\n" + "when\n" + " $b : Bean( value > 0 )\n" + "then\n" + " list.add( $b.getValue() );\n" + "end\n"; KieFileSystem kfs = createKieFileSystemWithKProject(ks, false, kbaseName, "KSession1"); kfs.writePomXML(getPom(releaseId)); kfs.write("src/main/resources/KBase1/rule1.drl", drl) .write("src/main/java/org/kie/test/Bean.java", createJavaSource(factor)); KieBuilder kieBuilder = ks.newKieBuilder(kfs); assertTrue(kieBuilder.buildAll().getResults().getMessages().isEmpty()); return (InternalKieModule) kieBuilder.getKieModule(); } }