/*
* 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.drools.compiler.integrationtests;
import org.drools.compiler.CommonTestMethodBase;
import org.drools.compiler.Message;
import org.drools.compiler.kie.builder.impl.InternalKieModule;
import org.junit.Test;
import org.kie.api.KieBase;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.KieModule;
import org.kie.api.builder.ReleaseId;
import org.kie.api.builder.Results;
import org.kie.api.builder.model.KieModuleModel;
import org.kie.api.io.Resource;
import org.kie.api.io.ResourceType;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.conf.ClockTypeOption;
import org.kie.internal.builder.InternalKieBuilder;
import org.kie.internal.io.ResourceFactory;
import java.util.List;
import java.util.function.Predicate;
public class KieBuilderTest extends CommonTestMethodBase {
@Test
public void testResourceInclusion() {
String drl1 = "package org.drools.compiler\n" +
"rule R1 when\n" +
" $m : Message()\n" +
"then\n" +
"end\n";
String drl2 = "package org.drools.compiler\n" +
"rule R2 when\n" +
" $m : Message( message == \"Hi Universe\" )\n" +
"then\n" +
"end\n";
String drl3 = "package org.drools.compiler\n" +
"rule R3 when\n" +
" $m : Message( message == \"Hello World\" )\n" +
"then\n" +
"end\n";
String drl4 = "package org.drools.compiler\n" +
"rule R4 when\n" +
" $m : Message( message == \"Hello Earth\" )\n" +
"then\n" +
"end\n";
String kmodule = "<kmodule xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n" +
" xmlns=\"http://www.drools.org/xsd/kmodule\">\n" +
" <kbase name=\"kbase1\" default=\"true\" eventProcessingMode=\"stream\" equalsBehavior=\"identity\" scope=\"javax.enterprise.context.ApplicationScoped\">\n" +
" <ksession name=\"ksession1\" type=\"stateful\" default=\"true\" clockType=\"realtime\" scope=\"javax.enterprise.context.ApplicationScoped\"/>\n" +
" </kbase>\n" +
"</kmodule>";
KieServices ks = KieServices.Factory.get();
// Create an in-memory jar for version 1.0.0
ReleaseId releaseId1 = ks.newReleaseId( "org.kie", "test-kie-builder", "1.0.0" );
Resource r1 = ResourceFactory.newByteArrayResource( drl1.getBytes() ).setResourceType( ResourceType.DRL ).setSourcePath( "kbase1/drl1.drl" );
Resource r2 = ResourceFactory.newByteArrayResource( drl2.getBytes() ).setResourceType( ResourceType.GDRL ).setSourcePath( "kbase1/drl2.gdrl" );
Resource r3 = ResourceFactory.newByteArrayResource( drl3.getBytes() ).setResourceType( ResourceType.RDRL ).setSourcePath( "kbase1/drl3.rdrl" );
Resource r4 = ResourceFactory.newByteArrayResource( drl4.getBytes() ).setResourceType( ResourceType.TDRL ).setSourcePath( "kbase1/drl4.tdrl" );
KieModule km = createAndDeployJar( ks,
kmodule,
releaseId1,
r1,
r2,
r3,
r4 );
InternalKieModule ikm = (InternalKieModule) km;
assertNotNull( ikm.getResource( r1.getSourcePath() ) );
assertNotNull( ikm.getResource( r2.getSourcePath() ) );
assertNotNull( ikm.getResource( r3.getSourcePath() ) );
assertNotNull( ikm.getResource( r4.getSourcePath() ) );
// Create a session and fire rules
KieContainer kc = ks.newKieContainer( km.getReleaseId() );
KieSession ksession = kc.newKieSession();
ksession.insert( new Message( "Hello World" ) );
assertEquals( 2, ksession.fireAllRules() );
ksession.dispose();
}
@Test
public void testValidXsdTargetNamespace() {
String drl1 = "package org.drools.compiler\n" +
"rule R1 when\n" +
" $m : Message()\n" +
"then\n" +
"end\n";
String kmodule = "<kmodule xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n" +
" xmlns=\"http://www.drools.org/xsd/kmodule\">\n" +
" <kbase name=\"kbase1\">\n" +
" <ksession name=\"ksession1\" default=\"true\"/>\n" +
" </kbase>\n" +
"</kmodule>";
KieServices ks = KieServices.Factory.get();
ReleaseId releaseId1 = ks.newReleaseId( "org.kie", "test-kie-builder", "1.0.0" );
Resource r1 = ResourceFactory.newByteArrayResource( drl1.getBytes() ).setResourceType( ResourceType.DRL ).setSourcePath( "kbase1/drl1.drl" );
KieModule km = createAndDeployJar( ks,
kmodule,
releaseId1,
r1);
ks.newKieContainer( km.getReleaseId() );
}
@Test(expected = RuntimeException.class) // TODO Should be a validation exception, but createAndDeployJar throws NPE
public void testInvalidXsdTargetNamespace() {
String drl1 = "package org.drools.compiler\n" +
"rule R1 when\n" +
" $m : Message()\n" +
"then\n" +
"end\n";
String kmodule = "<kmodule xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n" +
" xmlns=\"http://www.drools.org/xsd/doesNotExist\">\n" +
" <kbase name=\"kbase1\">\n" +
" <ksession name=\"ksession1\" default=\"true\"/>\n" +
" </kbase>\n" +
"</kmodule>";
KieServices ks = KieServices.Factory.get();
// Create an in-memory jar for version 1.0.0
ReleaseId releaseId1 = ks.newReleaseId( "org.kie", "test-kie-builder", "1.0.0" );
Resource r1 = ResourceFactory.newByteArrayResource( drl1.getBytes() ).setResourceType( ResourceType.DRL ).setSourcePath( "kbase1/drl1.drl" );
KieModule km = createAndDeployJar( ks,
kmodule,
releaseId1,
r1);
ks.newKieContainer( km.getReleaseId() );
}
@Test
public void testOldXsdTargetNamespace() {
String drl1 = "package org.drools.compiler\n" +
"rule R1 when\n" +
" $m : Message()\n" +
"then\n" +
"end\n";
String kmodule = "<kmodule xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n" +
" xmlns=\"http://jboss.org/kie/6.0.0/kmodule\">\n" +
" <kbase name=\"kbase1\">\n" +
" <ksession name=\"ksession1\" default=\"true\"/>\n" +
" </kbase>\n" +
"</kmodule>";
KieServices ks = KieServices.Factory.get();
// Create an in-memory jar for version 1.0.0
ReleaseId releaseId1 = ks.newReleaseId( "org.kie", "test-kie-builder", "1.0.0" );
Resource r1 = ResourceFactory.newByteArrayResource( drl1.getBytes() ).setResourceType( ResourceType.DRL ).setSourcePath( "kbase1/drl1.drl" );
KieModule km = createAndDeployJar( ks,
kmodule,
releaseId1,
r1);
ks.newKieContainer( km.getReleaseId() );
}
@Test
public void testGetKieBaseAfterKieSessionCreation() {
final String KBASE_NAME = "kieBase";
final String KSESSION_NAME = "kieSession";
String drl = "declare TestEvent\n" +
" @role( event )\n" +
" name : String\n" +
"end\n" +
"\n" +
"declare window DeclaredTimeWindow\n" +
" TestEvent ( name == \"timeDec\" ) over window:time( 50ms ) from entry-point EventStream\n" +
"end";
KieServices ks = KieServices.Factory.get();
KieFileSystem kfs = ks.newKieFileSystem();
kfs.write( "src/main/resources/window.drl", drl );
KieModuleModel kmoduleModel = ks.newKieModuleModel();
kmoduleModel.newKieBaseModel( KBASE_NAME )
.addPackage( "*" )
.newKieSessionModel( KSESSION_NAME )
.setDefault( true )
.setClockType( ClockTypeOption.get( "pseudo" ) );
kfs.writeKModuleXML( kmoduleModel.toXML() );
KieBuilder builder = ks.newKieBuilder( kfs ).buildAll();
assertEquals( 0, builder.getResults().getMessages().size() );
ks.getRepository().addKieModule( builder.getKieModule() );
KieSession kieSession = ks.newKieContainer( ks.getRepository().getDefaultReleaseId() ).newKieSession( KSESSION_NAME );
assertNotNull( kieSession );
KieBase kieBase = ks.newKieContainer( ks.getRepository().getDefaultReleaseId() ).getKieBase( KBASE_NAME );
assertNotNull( kieBase );
}
@Test
public void testReportKBuilderErrorWhenUsingAJavaClassWithNoPkg() throws Exception {
// BZ-995018
String java = "public class JavaClass { }\n";
KieServices ks = KieServices.Factory.get();
KieFileSystem kfs = ks.newKieFileSystem()
.write( "src/main/java/JavaClass.java", java );
Results results = ks.newKieBuilder( kfs ).buildAll().getResults();
System.out.println( results.getMessages() );
assertEquals( 1, results.getMessages().size() );
}
@Test
public void testJavaSourceFileAndDrlDeploy() {
String java = "package org.drools.compiler;\n" +
"public class JavaSourceMessage { }\n";
String drl = "package org.drools.compiler;\n" +
"import org.drools.compiler.JavaSourceMessage;" +
"rule R1 when\n" +
" $m : JavaSourceMessage()\n" +
"then\n" +
"end\n";
String kmodule = "<kmodule xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n" +
" xmlns=\"http://www.drools.org/xsd/kmodule\">\n" +
" <kbase name=\"kbase1\">\n" +
" <ksession name=\"ksession1\" default=\"true\"/>\n" +
" </kbase>\n" +
"</kmodule>";
KieServices ks = KieServices.Factory.get();
ReleaseId releaseId1 = ks.newReleaseId( "org.kie", "test-kie-builder", "1.0.0" );
Resource javaResource = ResourceFactory.newByteArrayResource( java.getBytes() ).setResourceType( ResourceType.JAVA )
.setSourcePath( "org/drools/compiler/JavaSourceMessage.java" );
Resource drlResource = ResourceFactory.newByteArrayResource( drl.getBytes() ).setResourceType( ResourceType.DRL )
.setSourcePath( "kbase1/drl1.drl" );
KieModule km = createAndDeployJar( ks,
kmodule,
releaseId1,
javaResource, drlResource);
KieContainer kieContainer = ks.newKieContainer(km.getReleaseId());
try {
Class<?> messageClass = kieContainer.getClassLoader().loadClass("org.drools.compiler.JavaSourceMessage");
assertNotNull(messageClass);
} catch (ClassNotFoundException e) {
throw new IllegalStateException("Loading the java class failed.", e);
}
}
@Test
public void testJavaSourceFileAndDrlDeployWithClassFilter() {
String allowedJava = "package org.drools.compiler;\n" +
"public class JavaSourceMessage { }\n";
String filteredJava = "package org.drools.compiler;\n" +
"public class ClassCausingClassNotFoundException { non.existing.Type foo() { return null; } }\n";
String drl = "package org.drools.compiler;\n" +
"import org.drools.compiler.JavaSourceMessage;" +
"rule R1 when\n" +
" $m : JavaSourceMessage()\n" +
"then\n" +
"end\n";
String kmodule = "<kmodule xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n" +
" xmlns=\"http://www.drools.org/xsd/kmodule\">\n" +
" <kbase name=\"kbase1\">\n" +
" <ksession name=\"ksession1\" default=\"true\"/>\n" +
" </kbase>\n" +
"</kmodule>";
KieServices ks = KieServices.Factory.get();
ReleaseId releaseId1 = ks.newReleaseId( "org.kie", "test-kie-builder", "1.0.0" );
Resource allowedJavaResource = ResourceFactory.newByteArrayResource( allowedJava.getBytes() ).setResourceType( ResourceType.JAVA )
.setSourcePath( "org/drools/compiler/JavaSourceMessage.java" );
Resource filteredJavaResource = ResourceFactory.newByteArrayResource( filteredJava.getBytes() ).setResourceType( ResourceType.JAVA )
.setSourcePath( "org/drools/compiler/ClassCausingClassNotFoundException.java" );
Resource drlResource = ResourceFactory.newByteArrayResource( drl.getBytes() ).setResourceType( ResourceType.DRL )
.setSourcePath( "kbase1/drl1.drl" );
Predicate<String> filter = fileName -> !fileName.endsWith( "org/drools/compiler/ClassCausingClassNotFoundException.java" );
KieModule km = null;
try {
km = createAndDeployJar( ks,
kmodule,
filter,
releaseId1,
allowedJavaResource, filteredJavaResource, drlResource);
} catch ( IllegalStateException ise ) {
if ( ise.getMessage().contains( "org/drools/compiler/ClassCausingClassNotFoundException.java" ) ) {
fail( "Build failed because source file was not filtered out." );
} else {
throw ise;
}
}
KieContainer kieContainer = ks.newKieContainer(km.getReleaseId());
try {
Class<?> messageClass = kieContainer.getClassLoader().loadClass("org.drools.compiler.JavaSourceMessage");
assertNotNull(messageClass);
} catch (ClassNotFoundException e) {
throw new IllegalStateException("Loading the java class failed.", e);
}
}
@Test
public void testKieBuilderWithDotFiles() {
// BZ-1044409
final String KBASE_NAME = "kieBase";
final String KSESSION_NAME = "kieSession";
//This can be any DRL, or any file recognised by drools-compiler
String drl = "declare TestEvent\n" +
" name : String\n" +
"end\n";
String dotDrl = "Meta-data used by kie-wb";
KieServices ks = KieServices.Factory.get();
KieFileSystem kfs = ks.newKieFileSystem();
kfs.write( "src/main/resources/drlFile.drl", drl );
kfs.write( "src/main/resources/.drlFile.drl", dotDrl );
KieModuleModel kmoduleModel = ks.newKieModuleModel();
kmoduleModel.newKieBaseModel( KBASE_NAME )
.addPackage( "*" )
.newKieSessionModel( KSESSION_NAME )
.setDefault( true );
kfs.writeKModuleXML( kmoduleModel.toXML() );
KieBuilder builder = ks.newKieBuilder( kfs ).buildAll();
for ( org.kie.api.builder.Message m : builder.getResults().getMessages() ) {
System.out.println( m );
}
assertEquals( 0, builder.getResults().getMessages().size() );
ks.getRepository().addKieModule( builder.getKieModule() );
KieSession kieSession = ks.newKieContainer( ks.getRepository().getDefaultReleaseId() ).newKieSession( KSESSION_NAME );
assertNotNull( kieSession );
KieBase kieBase = ks.newKieContainer( ks.getRepository().getDefaultReleaseId() ).getKieBase( KBASE_NAME );
assertNotNull( kieBase );
}
@Test
public void testMultipleKBaseWithDrlError() {
// RHBRMS-2651
String drl = "package org.drools.compiler;\n" +
"rule \"test\"\n" +
" when\n" +
" Smurf\n" +
" then\n" +
"end";
KieServices ks = KieServices.Factory.get();
KieModuleModel kproj = ks.newKieModuleModel();
kproj.newKieBaseModel( "kbase1" ).newKieSessionModel( "ksession1" ).setDefault( true );
kproj.newKieBaseModel( "kbase2" ).newKieSessionModel( "ksession2" );
ReleaseId releaseId = ks.newReleaseId( "org.kie", "test-kie-builder", "1.0.0" );
KieFileSystem kfs = ks.newKieFileSystem().generateAndWritePomXML( releaseId ).writeKModuleXML( kproj.toXML() );
Resource drlResource = ResourceFactory.newByteArrayResource( drl.getBytes() ).setResourceType( ResourceType.DRL )
.setSourcePath( "kbase1/drl1.drl" );
kfs.write( "src/main/resources/org/drools/compiler/drl1.drl", drlResource );
KieBuilder kb = ks.newKieBuilder( kfs ).buildAll();
List<org.kie.api.builder.Message> messages = kb.getResults().getMessages( org.kie.api.builder.Message.Level.ERROR );
assertEquals( 4, messages.size() );
assertTrue( messages.get(0).toString().contains( "kbase1" ) );
assertTrue( messages.get(1).toString().contains( "kbase1" ) );
assertTrue( messages.get(2).toString().contains( "kbase2" ) );
assertTrue( messages.get(3).toString().contains( "kbase2" ) );
}
@Test
public void testBuildWithKBaseAndKSessionWithIdenticalNames() {
// RHBRMS-2689
String kmodule = "<kmodule xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n" +
" xmlns=\"http://www.drools.org/xsd/kmodule\">\n" +
" <kbase name=\"name\">\n" +
" <ksession name=\"name\" default=\"true\"/>\n" +
" </kbase>\n" +
"</kmodule>";
checkKModule( kmodule, 0 );
}
@Test
public void testBuildWithDuplicatedKSessionNames() {
// RHBRMS-2689
String kmodule = "<kmodule xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n" +
" xmlns=\"http://www.drools.org/xsd/kmodule\">\n" +
" <kbase name=\"kbase1\">\n" +
" <ksession name=\"ksessionA\" default=\"true\"/>\n" +
" </kbase>\n" +
" <kbase name=\"kbase2\">\n" +
" <ksession name=\"ksessionA\"/>\n" +
" </kbase>\n" +
"</kmodule>";
checkKModule( kmodule, 1 );
}
@Test
public void testBuildWithDuplicatedKBaseNames() {
// RHBRMS-2689
String kmodule = "<kmodule xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n" +
" xmlns=\"http://www.drools.org/xsd/kmodule\">\n" +
" <kbase name=\"kbase1\">\n" +
" <ksession name=\"ksessionA\" default=\"true\"/>\n" +
" </kbase>\n" +
" <kbase name=\"kbase1\">\n" +
" <ksession name=\"ksessionB\"/>\n" +
" </kbase>\n" +
"</kmodule>";
checkKModule( kmodule, 1 );
}
private void checkKModule( String kmodule, int expectedErrors ) {
KieServices ks = KieServices.Factory.get();
ReleaseId releaseId = ks.newReleaseId( "org.kie", "test-kie-builder", "1.0.0" );
KieFileSystem kfs = ks.newKieFileSystem().generateAndWritePomXML( releaseId ).writeKModuleXML( kmodule );
KieBuilder kieBuilder = ks.newKieBuilder( kfs );
((InternalKieBuilder) kieBuilder).buildAll();
Results results = kieBuilder.getResults();
assertEquals( expectedErrors, results.getMessages( org.kie.api.builder.Message.Level.ERROR ).size() );
}
}