org.drools.compiler.builder.impl.KnowledgeBuilderConfigurationImpl Maven / Gradle / Ivy
/*
* Copyright 2005 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.builder.impl;
import java.io.File;
import java.net.URL;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import org.drools.compiler.compiler.Dialect;
import org.drools.compiler.compiler.DialectCompiletimeRegistry;
import org.drools.compiler.compiler.DialectConfiguration;
import org.drools.compiler.compiler.DrlParser;
import org.drools.compiler.compiler.PackageRegistry;
import org.drools.compiler.compiler.xml.RulesSemanticModule;
import org.drools.compiler.kie.builder.impl.InternalKieModule.CompilationCache;
import org.drools.compiler.rule.builder.DroolsCompilerComponentFactory;
import org.drools.compiler.rule.builder.dialect.java.JavaDialectConfiguration;
import org.drools.compiler.rule.builder.dialect.mvel.MVELDialectConfiguration;
import org.drools.compiler.rule.builder.util.AccumulateUtil;
import org.drools.core.base.evaluators.EvaluatorDefinition;
import org.drools.core.base.evaluators.EvaluatorRegistry;
import org.drools.core.definitions.InternalKnowledgePackage;
import org.drools.core.factmodel.ClassBuilderFactory;
import org.drools.core.reteoo.KieComponentFactory;
import org.drools.core.util.ClassUtils;
import org.drools.core.util.ConfFileUtils;
import org.drools.core.util.StringUtils;
import org.drools.core.xml.ChangeSetSemanticModule;
import org.drools.core.xml.DefaultSemanticModule;
import org.drools.core.xml.Handler;
import org.drools.core.xml.SemanticModule;
import org.drools.core.xml.SemanticModules;
import org.drools.core.xml.WrapperSemanticModule;
import org.drools.reflective.classloader.ProjectClassLoader;
import org.kie.api.runtime.rule.AccumulateFunction;
import org.kie.internal.builder.KnowledgeBuilderConfiguration;
import org.kie.internal.builder.ResultSeverity;
import org.kie.internal.builder.conf.AccumulateFunctionOption;
import org.kie.internal.builder.conf.ClassLoaderCacheOption;
import org.kie.internal.builder.conf.DefaultDialectOption;
import org.kie.internal.builder.conf.DefaultPackageNameOption;
import org.kie.internal.builder.conf.DumpDirOption;
import org.kie.internal.builder.conf.EvaluatorOption;
import org.kie.internal.builder.conf.ExternaliseCanonicalModelLambdaOption;
import org.kie.internal.builder.conf.GroupDRLsInKieBasesByFolderOption;
import org.kie.internal.builder.conf.KBuilderSeverityOption;
import org.kie.internal.builder.conf.KnowledgeBuilderOption;
import org.kie.internal.builder.conf.LanguageLevelOption;
import org.kie.internal.builder.conf.MultiValueKnowledgeBuilderOption;
import org.kie.internal.builder.conf.ParallelRulesBuildThresholdOption;
import org.kie.internal.builder.conf.ProcessStringEscapesOption;
import org.kie.internal.builder.conf.PropertySpecificOption;
import org.kie.internal.builder.conf.SingleValueKnowledgeBuilderOption;
import org.kie.internal.builder.conf.TrimCellsInDTableOption;
import org.kie.internal.utils.ChainedProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.drools.core.reteoo.KieComponentFactory.createKieComponentFactory;
/**
* This class configures the package compiler.
* Dialects and their DialectConfigurations are handled by the DialectRegistry
* Normally you will not need to look at this class, unless you want to override the defaults.
*
* This class is not thread safe and it also contains state. Once it is created and used
* in one or more PackageBuilders it should be considered immutable. Do not modify its
* properties while it is being used by a PackageBuilder.
*
* drools.dialect.default =
* drools.accumulate.function. =
* drools.evaluator. =
* drools.dump.dir =
* drools.classLoaderCacheEnabled = true|false
* drools.parallelRulesBuildThreshold =
*
* default dialect is java.
* Available preconfigured Accumulate functions are:
* drools.accumulate.function.average = org.kie.base.accumulators.AverageAccumulateFunction
* drools.accumulate.function.max = org.kie.base.accumulators.MaxAccumulateFunction
* drools.accumulate.function.min = org.kie.base.accumulators.MinAccumulateFunction
* drools.accumulate.function.count = org.kie.base.accumulators.CountAccumulateFunction
* drools.accumulate.function.sum = org.kie.base.accumulators.SumAccumulateFunction
*
* drools.parser.processStringEscapes = true|false
*
*
* drools.problem.severity. = ERROR|WARNING|INFO
*
*/
public class KnowledgeBuilderConfigurationImpl
implements
KnowledgeBuilderConfiguration {
public static final String DEFAULT_PACKAGE = "defaultpkg";
private static final int DEFAULT_PARALLEL_RULES_BUILD_THRESHOLD = 10;
private final Map dialectConfigurations = new HashMap<>();
private DefaultDialectOption defaultDialect = DefaultDialectOption.get("java");
private ParallelRulesBuildThresholdOption parallelRulesBuildThreshold = ParallelRulesBuildThresholdOption.get(DEFAULT_PARALLEL_RULES_BUILD_THRESHOLD);
private ClassLoader classLoader;
private ChainedProperties chainedProperties;
private Map accumulateFunctions;
private EvaluatorRegistry evaluatorRegistry;
private SemanticModules semanticModules;
private File dumpDirectory;
private boolean processStringEscapes = true;
private boolean classLoaderCache = true;
private boolean trimCellsInDTable = true;
private boolean groupDRLsInKieBasesByFolder = false;
private boolean externaliseCanonicalModelLambda = true;
private static final PropertySpecificOption DEFAULT_PROP_SPEC_OPT = PropertySpecificOption.ALWAYS;
private PropertySpecificOption propertySpecificOption = DEFAULT_PROP_SPEC_OPT;
private String defaultPackageName;
private Map severityMap;
private DroolsCompilerComponentFactory componentFactory;
private ClassBuilderFactory classBuilderFactory;
private KieComponentFactory kieComponentFactory;
private LanguageLevelOption languageLevel = DrlParser.DEFAULT_LANGUAGE_LEVEL;
private CompilationCache compilationCache = null;
private static final Logger log = LoggerFactory.getLogger(KnowledgeBuilderConfigurationImpl.class);
/**
* Constructor that sets the parent class loader for the package being built/compiled
* @param classLoaders
*/
public KnowledgeBuilderConfigurationImpl(ClassLoader... classLoaders) {
init(null,
classLoaders);
}
/**
* Programmatic properties file, added with lease precedence
*/
public KnowledgeBuilderConfigurationImpl(Properties properties) {
init(properties,
(ClassLoader[]) null);
}
/**
* Programmatic properties file, added with lease precedence
*/
public KnowledgeBuilderConfigurationImpl(Properties properties,
ClassLoader... classLoaders) {
init(properties,
classLoaders);
}
public KnowledgeBuilderConfigurationImpl() {
init(null,
(ClassLoader[]) null);
}
private void init(Properties properties,
ClassLoader... classLoaders) {
if (classLoaders != null && classLoaders.length > 1) {
throw new RuntimeException("Multiple classloaders are no longer supported");
}
setClassLoader(classLoaders == null || classLoaders.length == 0 ? null : classLoaders[0]);
init(properties);
}
private void init(Properties properties) {
this.chainedProperties = ChainedProperties.getChainedProperties( getClassLoader() );
if (chainedProperties.getProperty("drools.dialect.java", null) == null) {
// if it couldn't find a conf for java dialect using the project class loader
// it means it could not load the conf file at all (very likely it is running in
// an osgi environement) so try with the class loader of this class
this.chainedProperties = ChainedProperties.getChainedProperties( getClass().getClassLoader() );
if (this.classLoader instanceof ProjectClassLoader ) {
((ProjectClassLoader) classLoader).setDroolsClassLoader(getClass().getClassLoader());
}
}
if (properties != null) {
this.chainedProperties.addProperties(properties);
}
setProperty(ClassLoaderCacheOption.PROPERTY_NAME,
this.chainedProperties.getProperty(ClassLoaderCacheOption.PROPERTY_NAME,
"true"));
setProperty( TrimCellsInDTableOption.PROPERTY_NAME,
this.chainedProperties.getProperty(TrimCellsInDTableOption.PROPERTY_NAME,
"true"));
setProperty( GroupDRLsInKieBasesByFolderOption.PROPERTY_NAME,
this.chainedProperties.getProperty(GroupDRLsInKieBasesByFolderOption.PROPERTY_NAME,
"false"));
setProperty(PropertySpecificOption.PROPERTY_NAME,
this.chainedProperties.getProperty(PropertySpecificOption.PROPERTY_NAME,
DEFAULT_PROP_SPEC_OPT.toString()));
setProperty(LanguageLevelOption.PROPERTY_NAME,
this.chainedProperties.getProperty(LanguageLevelOption.PROPERTY_NAME,
DrlParser.DEFAULT_LANGUAGE_LEVEL.toString()));
setProperty(ParallelRulesBuildThresholdOption.PROPERTY_NAME,
this.chainedProperties.getProperty(ParallelRulesBuildThresholdOption.PROPERTY_NAME,
String.valueOf(DEFAULT_PARALLEL_RULES_BUILD_THRESHOLD)));
buildDialectConfigurationMap();
this.accumulateFunctions = AccumulateUtil.buildAccumulateFunctionsMap(chainedProperties, getFunctionFactoryClassLoader() );
buildEvaluatorRegistry();
buildDumpDirectory();
buildSeverityMap();
setProperty(ProcessStringEscapesOption.PROPERTY_NAME,
this.chainedProperties.getProperty(ProcessStringEscapesOption.PROPERTY_NAME,
"true"));
setProperty(DefaultPackageNameOption.PROPERTY_NAME,
this.chainedProperties.getProperty(DefaultPackageNameOption.PROPERTY_NAME,
DEFAULT_PACKAGE));
setProperty(ExternaliseCanonicalModelLambdaOption.PROPERTY_NAME,
this.chainedProperties.getProperty(ExternaliseCanonicalModelLambdaOption.PROPERTY_NAME,"true"));
this.componentFactory = new DroolsCompilerComponentFactory();
this.kieComponentFactory = createKieComponentFactory();
this.classBuilderFactory = kieComponentFactory.getClassBuilderFactory();
}
protected ClassLoader getFunctionFactoryClassLoader() {
return getClassLoader();
}
private void buildSeverityMap() {
this.severityMap = new HashMap();
Map temp = new HashMap();
this.chainedProperties.mapStartsWith(temp,
KBuilderSeverityOption.PROPERTY_NAME,
true);
int index = KBuilderSeverityOption.PROPERTY_NAME.length();
for (Map.Entry entry : temp.entrySet()) {
String identifier = entry.getKey().trim().substring(index);
this.severityMap.put(identifier,
KBuilderSeverityOption.get(identifier, entry.getValue()).getSeverity());
}
}
public void setProperty(String name,
String value) {
name = name.trim();
if (StringUtils.isEmpty(name)) {
return;
}
if (name.equals(DefaultDialectOption.PROPERTY_NAME)) {
setDefaultDialect(value);
} else if (name.startsWith(AccumulateFunctionOption.PROPERTY_NAME)) {
addAccumulateFunction(name.substring(AccumulateFunctionOption.PROPERTY_NAME.length()),
value);
} else if (name.startsWith(EvaluatorOption.PROPERTY_NAME)) {
this.evaluatorRegistry.addEvaluatorDefinition(value);
} else if (name.equals(DumpDirOption.PROPERTY_NAME)) {
buildDumpDirectory(value);
} else if (name.equals(DefaultPackageNameOption.PROPERTY_NAME)) {
setDefaultPackageName(value);
} else if (name.equals(ProcessStringEscapesOption.PROPERTY_NAME)) {
setProcessStringEscapes(Boolean.parseBoolean(value));
} else if (name.equals(ClassLoaderCacheOption.PROPERTY_NAME)) {
setClassLoaderCacheEnabled(Boolean.parseBoolean(value));
} else if (name.equals(TrimCellsInDTableOption.PROPERTY_NAME)) {
setTrimCellsInDTable(Boolean.parseBoolean(value));
} else if (name.equals(GroupDRLsInKieBasesByFolderOption.PROPERTY_NAME)) {
setGroupDRLsInKieBasesByFolder(Boolean.parseBoolean(value));
} else if (name.startsWith(KBuilderSeverityOption.PROPERTY_NAME)) {
String key = name.substring(name.lastIndexOf('.') + 1);
this.severityMap.put(key, KBuilderSeverityOption.get(key, value).getSeverity());
} else if (name.equals(PropertySpecificOption.PROPERTY_NAME)) {
try {
setPropertySpecificOption(PropertySpecificOption.valueOf(value.toUpperCase()));
} catch (IllegalArgumentException e) {
log.warn("Invalid value " + value + " for option " + PropertySpecificOption.PROPERTY_NAME);
}
} else if (name.equals(LanguageLevelOption.PROPERTY_NAME)) {
try {
setLanguageLevel(LanguageLevelOption.valueOf(value.toUpperCase()));
} catch (IllegalArgumentException e) {
log.warn("Invalid value " + value + " for option " + LanguageLevelOption.PROPERTY_NAME);
}
} else if (name.equals(ParallelRulesBuildThresholdOption.PROPERTY_NAME)) {
setParallelRulesBuildThreshold(Integer.valueOf(value));
} else if (name.equals(ExternaliseCanonicalModelLambdaOption.PROPERTY_NAME)) {
setExternaliseCanonicalModelLambda(Boolean.valueOf(value));
} else {
// if the property from the kmodule was not intercepted above, just add it to the chained properties.
Properties additionalProperty = new Properties();
additionalProperty.setProperty(name, value);
chainedProperties.addProperties(additionalProperty);
}
}
public String getProperty(String name) {
name = name.trim();
if (StringUtils.isEmpty(name)) {
return null;
}
if (name.equals(DefaultDialectOption.PROPERTY_NAME)) {
return getDefaultDialect();
} else if (name.equals(DefaultPackageNameOption.PROPERTY_NAME)) {
return getDefaultPackageName();
} else if (name.startsWith(AccumulateFunctionOption.PROPERTY_NAME)) {
int index = AccumulateFunctionOption.PROPERTY_NAME.length();
AccumulateFunction function = this.accumulateFunctions.get(name.substring(index));
return function != null ? function.getClass().getName() : null;
} else if (name.startsWith(EvaluatorOption.PROPERTY_NAME)) {
String key = name.substring(name.lastIndexOf('.') + 1);
EvaluatorDefinition evalDef = this.evaluatorRegistry.getEvaluatorDefinition(key);
return evalDef != null ? evalDef.getClass().getName() : null;
} else if (name.equals(DumpDirOption.PROPERTY_NAME)) {
return this.dumpDirectory != null ? this.dumpDirectory.toString() : null;
} else if (name.equals(ProcessStringEscapesOption.PROPERTY_NAME)) {
return String.valueOf(isProcessStringEscapes());
} else if (name.equals(ClassLoaderCacheOption.PROPERTY_NAME)) {
return String.valueOf(isClassLoaderCacheEnabled());
} else if (name.equals(TrimCellsInDTableOption.PROPERTY_NAME)) {
return String.valueOf(isTrimCellsInDTable());
} else if (name.equals(GroupDRLsInKieBasesByFolderOption.PROPERTY_NAME)) {
return String.valueOf(isGroupDRLsInKieBasesByFolder());
} else if (name.startsWith(KBuilderSeverityOption.PROPERTY_NAME)) {
String key = name.substring(name.lastIndexOf('.') + 1);
ResultSeverity severity = this.severityMap.get(key);
return severity.toString();
} else if (name.equals(LanguageLevelOption.PROPERTY_NAME)) {
return "" + getLanguageLevel();
} else if (name.equals(ParallelRulesBuildThresholdOption.PROPERTY_NAME)) {
return String.valueOf(getParallelRulesBuildThreshold());
} else if (name.equals(ExternaliseCanonicalModelLambdaOption.PROPERTY_NAME)) {
return String.valueOf(isExternaliseCanonicalModelLambda());
}
return null;
}
public ChainedProperties getChainedProperties() {
return this.chainedProperties;
}
private void buildDialectConfigurationMap() {
DialectConfiguration mvel = new MVELDialectConfiguration();
mvel.init(this);
dialectConfigurations.put("mvel", mvel);
DialectConfiguration java = new JavaDialectConfiguration();
java.init(this);
dialectConfigurations.put("java", java);
Map dialectProperties = new HashMap();
this.chainedProperties.mapStartsWith(dialectProperties, "drools.dialect", false);
setDefaultDialect(dialectProperties.get(DefaultDialectOption.PROPERTY_NAME));
}
public void addDialect(String dialectName,
DialectConfiguration dialectConf) {
dialectConfigurations.put(dialectName,
dialectConf);
}
public DialectCompiletimeRegistry buildDialectRegistry(ClassLoader rootClassLoader,
KnowledgeBuilderConfigurationImpl pkgConf,
PackageRegistry pkgRegistry,
InternalKnowledgePackage pkg) {
DialectCompiletimeRegistry registry = new DialectCompiletimeRegistry();
for (DialectConfiguration conf : this.dialectConfigurations.values()) {
Dialect dialect = conf.newDialect(rootClassLoader, pkgConf, pkgRegistry, pkg);
registry.addDialect(dialect.getId(), dialect);
}
return registry;
}
public String getDefaultDialect() {
return this.defaultDialect.getName();
}
public void setDefaultDialect(String defaultDialect) {
this.defaultDialect = DefaultDialectOption.get(defaultDialect);
}
public DialectConfiguration getDialectConfiguration(String name) {
return this.dialectConfigurations.get(name);
}
public void setDialectConfiguration(String name,
DialectConfiguration configuration) {
this.dialectConfigurations.put(name,
configuration);
}
public ClassLoader getClassLoader() {
return this.classLoader;
}
/** Use this to override the classLoader that will be used for the rules. */
private void setClassLoader(ClassLoader classLoader) {
this.classLoader = ProjectClassLoader.getClassLoader(classLoader,
getClass(),
isClassLoaderCacheEnabled());
}
public void addSemanticModule(SemanticModule module) {
if (this.semanticModules == null) {
initSemanticModules();
}
this.semanticModules.addSemanticModule(module);
}
public SemanticModules getSemanticModules() {
if (this.semanticModules == null) {
initSemanticModules();
}
return this.semanticModules;
}
public void initSemanticModules() {
this.semanticModules = new SemanticModules();
RulesSemanticModule ruleModule = new RulesSemanticModule("http://ddefault");
this.semanticModules.addSemanticModule(new WrapperSemanticModule("http://drools.org/drools-5.0", ruleModule));
this.semanticModules.addSemanticModule(new WrapperSemanticModule("http://drools.org/drools-5.2", ruleModule));
this.semanticModules.addSemanticModule(new ChangeSetSemanticModule());
// split on each space
String locations[] = this.chainedProperties.getProperty("semanticModules",
"").split("\\s");
// load each SemanticModule
for (String moduleLocation : locations) {
// trim leading/trailing spaces and quotes
moduleLocation = moduleLocation.trim();
if (moduleLocation.startsWith("\"")) {
moduleLocation = moduleLocation.substring(1);
}
if (moduleLocation.endsWith("\"")) {
moduleLocation = moduleLocation.substring(0,
moduleLocation.length() - 1);
}
if (!moduleLocation.equals("")) {
loadSemanticModule(moduleLocation);
}
}
}
public void loadSemanticModule(String moduleLocation) {
URL url = ConfFileUtils.getURL(moduleLocation,
getClassLoader(),
getClass());
if (url == null) {
throw new IllegalArgumentException(moduleLocation + " is specified but cannot be found.'");
}
Properties properties = ConfFileUtils.getProperties(url);
if (properties == null) {
throw new IllegalArgumentException(moduleLocation + " is specified but cannot be found.'");
}
loadSemanticModule(properties);
}
public void loadSemanticModule(Properties properties) {
String uri = properties.getProperty("uri",
null);
if (uri == null || uri.trim().equals("")) {
throw new RuntimeException("Semantic Module URI property must not be empty");
}
DefaultSemanticModule module = new DefaultSemanticModule(uri);
for (Entry
© 2015 - 2025 Weber Informatics LLC | Privacy Policy