org.drools.compiler.compiler.PackageBuilderConfiguration Maven / Gradle / Ivy
/*
* Copyright 2005 JBoss Inc
*
* 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.compiler;
import java.io.File;
import java.net.URL;
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.xml.RulesSemanticModule;
import org.drools.compiler.rule.builder.DroolsCompilerComponentFactory;
import org.drools.core.RuntimeDroolsException;
import org.drools.core.base.evaluators.EvaluatorDefinition;
import org.drools.core.base.evaluators.EvaluatorRegistry;
import org.drools.core.common.ProjectClassLoader;
import org.drools.core.factmodel.ClassBuilderFactory;
import org.drools.core.rule.Package;
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.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.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.ProcessStringEscapesOption;
import org.kie.internal.builder.conf.PropertySpecificOption;
import org.kie.internal.builder.conf.SingleValueKnowledgeBuilderOption;
import org.kie.internal.utils.ChainedProperties;
import org.kie.internal.utils.ClassLoaderUtil;
import org.kie.internal.utils.CompositeClassLoader;
import static org.drools.core.common.ProjectClassLoader.createProjectClassLoader;
/**
* 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
*
* 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 PackageBuilderConfiguration
implements
KnowledgeBuilderConfiguration {
private Map dialectConfigurations;
private DefaultDialectOption defaultDialect;
private ClassLoader classLoader;
private ChainedProperties chainedProperties;
private Map accumulateFunctions;
private EvaluatorRegistry evaluatorRegistry;
private SemanticModules semanticModules;
private File dumpDirectory;
private boolean allowMultipleNamespaces = true;
private boolean processStringEscapes = true;
private boolean classLoaderCache = true;
private PropertySpecificOption propertySpecificOption = PropertySpecificOption.ALLOWED;
private String defaultPackageName;
private Map severityMap;
private DroolsCompilerComponentFactory componentFactory;
private ClassBuilderFactory classBuilderFactory;
private LanguageLevelOption languageLevel = DrlParser.DEFAULT_LANGUAGE_LEVEL;
private Map> compilationCache = null;
public boolean isAllowMultipleNamespaces() {
return allowMultipleNamespaces;
}
/**
* By default multiple namespaces are allowed. If you set this to "false" it will
* make it all happen in the "default" namespace (the first namespace you define).
*/
public void setAllowMultipleNamespaces(boolean allowMultipleNamespaces) {
this.allowMultipleNamespaces = allowMultipleNamespaces;
}
/**
* Constructor that sets the parent class loader for the package being built/compiled
* @param classLoaders
*/
public PackageBuilderConfiguration(ClassLoader... classLoaders) {
init( null,
classLoaders );
}
/**
* Programmatic properties file, added with lease precedence
* @param properties
*/
public PackageBuilderConfiguration(Properties properties) {
init( properties,
(ClassLoader[]) null );
}
/**
* Programmatic properties file, added with lease precedence
* @param classLoaders
* @param properties
*/
public PackageBuilderConfiguration(Properties properties,
ClassLoader... classLoaders) {
init( properties,
classLoaders );
}
public PackageBuilderConfiguration(Properties properties,
CompositeClassLoader classLoader) {
init( properties,
classLoader );
}
public PackageBuilderConfiguration() {
init( null,
(ClassLoader[]) null );
}
private void init(Properties properties,
CompositeClassLoader classLoader) {
this.classLoader = classLoader;
init( properties );
}
private void init(Properties properties,
ClassLoader... classLoaders) {
setClassLoader( classLoaders );
init( properties );
}
private void init(Properties properties) {
this.chainedProperties = new ChainedProperties( "packagebuilder.conf",
getClassLoader(),
true );
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 = new ChainedProperties( "packagebuilder.conf",
getClass().getClassLoader(),
true );
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" ) );
this.dialectConfigurations = new HashMap();
buildDialectConfigurationMap();
buildAccumulateFunctionsMap();
buildEvaluatorRegistry();
buildDumpDirectory();
buildSeverityMap();
setProperty( ProcessStringEscapesOption.PROPERTY_NAME,
this.chainedProperties.getProperty( ProcessStringEscapesOption.PROPERTY_NAME,
"true" ) );
setProperty( DefaultPackageNameOption.PROPERTY_NAME,
this.chainedProperties.getProperty( DefaultPackageNameOption.PROPERTY_NAME,
"defaultpkg" ) );
this.componentFactory = new DroolsCompilerComponentFactory();
this.classBuilderFactory = new ClassBuilderFactory();
}
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.startsWith( KBuilderSeverityOption.PROPERTY_NAME ) ) {
String key = name.substring( name.lastIndexOf( '.' ) + 1 );
this.severityMap.put( key, KBuilderSeverityOption.get( key, value ).getSeverity() );
} else if ( name.equals( LanguageLevelOption.PROPERTY_NAME ) ) {
setLanguageLevel( LanguageLevelOption.valueOf( value ) );
}
}
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.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();
}
return null;
}
public ChainedProperties getChainedProperties() {
return this.chainedProperties;
}
private void buildDialectConfigurationMap() {
//DialectRegistry registry = new DialectRegistry();
Map dialectProperties = new HashMap();
this.chainedProperties.mapStartsWith( dialectProperties,
"drools.dialect",
false );
setDefaultDialect( (String) dialectProperties.remove( DefaultDialectOption.PROPERTY_NAME ) );
for ( Map.Entry entry : dialectProperties.entrySet() ) {
String str = entry.getKey();
String dialectName = str.substring( str.lastIndexOf( "." ) + 1 );
String dialectClass = entry.getValue();
addDialect( dialectName, dialectClass );
}
}
public void addDialect(String dialectName,
String dialectClass) {
Class> cls = null;
try {
cls = getClassLoader().loadClass(dialectClass);
DialectConfiguration dialectConf = (DialectConfiguration) cls.newInstance();
dialectConf.init( this );
addDialect( dialectName,
dialectConf );
} catch ( Exception e ) {
throw new RuntimeDroolsException( "Unable to load dialect '" + dialectClass + ":" + dialectName + ":" + ((cls != null) ? cls.getName() : "null") + "'",
e );
}
}
public void addDialect(String dialectName,
DialectConfiguration dialectConf) {
dialectConfigurations.put( dialectName,
dialectConf );
}
public DialectCompiletimeRegistry buildDialectRegistry(PackageBuilder packageBuilder,
PackageRegistry pkgRegistry,
Package pkg) {
DialectCompiletimeRegistry registry = new DialectCompiletimeRegistry();
for ( DialectConfiguration conf : this.dialectConfigurations.values() ) {
Dialect dialect = conf.newDialect( packageBuilder, 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(final ClassLoader... classLoaders) {
this.classLoader = ProjectClassLoader.getClassLoader( classLoaders,
null,
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