Skip to content

Commit

Permalink
[DROOLS-7518] NullPointerException in MemoryFileSystem when kbase.nam…
Browse files Browse the repository at this point in the history
…e is empty in kmodule.xml (apache#5414)
  • Loading branch information
tkobayas authored Aug 2, 2023
1 parent df047c7 commit 02b43c7
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright 2023 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.drools.compiler.kproject;

public class KieModuleException extends RuntimeException {

public KieModuleException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import org.drools.compiler.kproject.KieModuleException;
import org.drools.core.util.AbstractXStreamConverter;
import org.drools.core.util.StringUtils;
import org.kie.api.builder.model.KieBaseModel;
Expand Down Expand Up @@ -432,6 +433,9 @@ public Object unmarshal(HierarchicalStreamReader reader,

String kbaseName = reader.getAttribute( "name" );
kBase.name = kbaseName != null ? kbaseName : StringUtils.uuid();
if (kBase.name.isEmpty()) {
throw new KieModuleException("kbase name is empty in kmodule.xml");
}

kBase.setDefault( "true".equals(reader.getAttribute( "default" )) );

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import org.drools.compiler.kproject.KieModuleException;
import org.drools.core.BeliefSystemType;
import org.drools.core.util.AbstractXStreamConverter;
import org.kie.api.builder.model.ChannelModel;
Expand Down Expand Up @@ -340,6 +341,9 @@ public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingCo
public Object unmarshal(HierarchicalStreamReader reader, final UnmarshallingContext context) {
final KieSessionModelImpl kSession = new KieSessionModelImpl();
kSession.name = reader.getAttribute("name");
if (kSession.name.isEmpty()) {
throw new KieModuleException("ksession name is empty in kmodule.xml");
}
kSession.setDefault( "true".equals(reader.getAttribute( "default" )) );
kSession.setDirectFiring( "true".equals(reader.getAttribute( "directFiring" )) );
kSession.setThreadSafe( "true".equals(reader.getAttribute( "threadSafe" )) );
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* Copyright 2023 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.mvel.integrationtests;

import java.util.Collection;
import java.util.List;

import org.drools.testcoverage.common.util.KieBaseTestConfiguration;
import org.drools.testcoverage.common.util.KieUtil;
import org.drools.testcoverage.common.util.TestParametersUtil;
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.Message;

import static org.assertj.core.api.Assertions.assertThat;

@RunWith(Parameterized.class)
public class KmoduleXmlTest {

enum Element {
KBASE,
KSESSION
}

private final KieBaseTestConfiguration kieBaseTestConfiguration;

public KmoduleXmlTest(final KieBaseTestConfiguration kieBaseTestConfiguration) {
this.kieBaseTestConfiguration = kieBaseTestConfiguration;
}

@Parameterized.Parameters(name = "KieBase type={0}")
public static Collection<Object[]> getParameters() {
return TestParametersUtil.getKieBaseCloudConfigurations(true);
}

@Test
public void kbaseEmptyName() throws Exception {
List<Message> errors = buildKmoduleWithEmptyValue("name", Element.KBASE);

assertThat(errors).isNotEmpty();
assertThat(errors.get(0).getText()).contains("kbase name is empty in kmodule.xml");
}

@Test
public void kbaseEmptyIncludes() throws Exception {
List<Message> errors = buildKmoduleWithEmptyValue("includes", Element.KBASE);

assertThat(errors).as("Empty includes is fine. It's ignored")
.isEmpty();
}

@Test
public void kbaseEmptyPackages() throws Exception {
List<Message> errors = buildKmoduleWithEmptyValue("packages", Element.KBASE);

assertThat(errors).as("Empty packages is fine. It means the default package")
.isEmpty();
}

@Test
public void ksessionEmptyName() throws Exception {
List<Message> errors = buildKmoduleWithEmptyValue("name", Element.KSESSION);

assertThat(errors).isNotEmpty();
assertThat(errors.get(0).getText()).contains("ksession name is empty in kmodule.xml");
}

private List<Message> buildKmoduleWithEmptyValue(String emptyAttribute, Element element) throws Exception {
String drl =
"package org.example\n" +
"rule R1 when\n" +
"then\n" +
"end\n";

KieServices ks = KieServices.Factory.get();

KieFileSystem kfs = ks.newKieFileSystem();
kfs.write("src/main/resources/org/example/r1.drl", drl);
kfs.write("src/main/resources/META-INF/kmodule.xml", getKmoduleString(emptyAttribute, element));
final KieBuilder kieBuilder = KieUtil.getKieBuilderFromKieFileSystem(kieBaseTestConfiguration, kfs, false);

return kieBuilder.getResults().getMessages(Message.Level.ERROR);
}

private String getKmoduleString(String emptyAttribute, Element element) {
StringBuilder sb = new StringBuilder();
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
sb.append("<kmodule xmlns=\"http://www.drools.org/xsd/kmodule\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n");
if (element == Element.KBASE) {
// if kbase name is omitted, UUID is given to its name
sb.append("<kbase " + emptyAttribute + "=\"\" default=\"true\">\n");
sb.append(" <ksession name=\"myKsession\" default=\"true\"/>\n");
} else if (element == Element.KSESSION) {
sb.append("<kbase name=\"myKbase\" default=\"true\">\n");
// if you test an attribute other than "name" in ksession, you need to add "name" attribute as it's required
sb.append(" <ksession " + emptyAttribute + "=\"\" default=\"true\"/>\n");
} else {
throw new IllegalArgumentException("Unsupported element : " + element);
}
sb.append("</kbase>\n");
sb.append("</kmodule>\n");
return sb.toString();
}
}

0 comments on commit 02b43c7

Please sign in to comment.