📄 packagebuilder.java
字号:
package org.drools.compiler;
/*
* 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.
*/
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.jci.compilers.CompilationResult;
import org.apache.commons.jci.compilers.EclipseJavaCompiler;
import org.apache.commons.jci.compilers.EclipseJavaCompilerSettings;
import org.apache.commons.jci.compilers.JavaCompiler;
import org.apache.commons.jci.compilers.JavaCompilerFactory;
import org.apache.commons.jci.problems.CompilationProblem;
import org.apache.commons.jci.readers.MemoryResourceReader;
import org.apache.commons.jci.readers.ResourceReader;
import org.drools.RuntimeDroolsException;
import org.drools.base.ClassFieldExtractorCache;
import org.drools.lang.descr.FunctionDescr;
import org.drools.lang.descr.PackageDescr;
import org.drools.lang.descr.PatternDescr;
import org.drools.lang.descr.RuleDescr;
import org.drools.rule.Package;
import org.drools.rule.Rule;
import org.drools.semantics.java.ClassTypeResolver;
import org.drools.semantics.java.FunctionBuilder;
import org.drools.semantics.java.PackageStore;
import org.drools.semantics.java.RuleBuilder;
import org.drools.spi.TypeResolver;
import org.drools.xml.XmlPackageReader;
import org.xml.sax.SAXException;
/**
* This is the main compiler class for parsing and compiling rules and assembling or merging them into a
* binary Package instance.
* This can be done by merging into existing binary packages, or totally from source.
*/
public class PackageBuilder {
private JavaCompiler compiler;
private Package pkg;
private List results;
private PackageStore packageStoreWrapper;
private MemoryResourceReader src;
private PackageBuilderConfiguration configuration;
private Map errorHandlers;
private List generatedClassList;
private ClassTypeResolver typeResolver;
private ClassFieldExtractorCache classFieldExtractorCache;
/**
* Use this when package is starting from scratch.
*/
public PackageBuilder() {
this( null,
null );
}
/**
* This will allow you to merge rules into this pre existing package.
*/
public PackageBuilder(final Package pkg) {
this( pkg,
null );
}
public PackageBuilder(PackageBuilderConfiguration configuration) {
this( null,
configuration );
}
/**
* This allows you to pass in a pre existing package, and a configuration (for instance to set the classloader).
* @param pkg A pre existing package (can be null if none exists)
* @param configuration Optional configuration for this builder.
*/
public PackageBuilder(final Package pkg,
PackageBuilderConfiguration configuration) {
if ( configuration == null ) {
configuration = new PackageBuilderConfiguration();
}
this.configuration = configuration;
loadCompiler();
this.src = new MemoryResourceReader();
this.results = new ArrayList();
this.errorHandlers = new HashMap();
this.pkg = pkg;
this.generatedClassList = new ArrayList();
this.classFieldExtractorCache = new ClassFieldExtractorCache();
if ( pkg != null ) {
this.packageStoreWrapper = new PackageStore( pkg.getPackageCompilationData() );
}
}
/**
* Load a rule package from DRL source.
* @param reader
* @throws DroolsParserException
* @throws IOException
*/
public void addPackageFromDrl(final Reader reader) throws DroolsParserException,
IOException {
final DrlParser parser = new DrlParser();
final PackageDescr pkg = parser.parse( reader );
this.results.addAll( parser.getErrors() );
addPackage( pkg );
}
/**
* Load a rule package from XML source.
* @param reader
* @throws DroolsParserException
* @throws IOException
*/
public void addPackageFromXml(final Reader reader) throws DroolsParserException,
IOException {
final XmlPackageReader xmlReader = new XmlPackageReader();
try {
xmlReader.read( reader );
} catch ( final SAXException e ) {
throw new DroolsParserException( e.getCause() );
}
addPackage( xmlReader.getPackageDescr() );
}
/**
* Load a rule package from DRL source using the supplied DSL configuration.
* @param source The source of the rules.
* @param dsl The source of the domain specific language configuration.
* @throws DroolsParserException
* @throws IOException
*/
public void addPackageFromDrl(final Reader source,
final Reader dsl) throws DroolsParserException,
IOException {
final DrlParser parser = new DrlParser();
final PackageDescr pkg = parser.parse( source,
dsl );
this.results.addAll( parser.getErrors() );
addPackage( pkg );
}
/**
* This adds a package from a Descr/AST
* This will also trigger a compile, if there are any generated classes to compile
* of course.
*/
public void addPackage(final PackageDescr packageDescr) {
validatePackageName( packageDescr );
validateUniqueRuleNames( packageDescr );
if ( this.pkg != null ) {
//mergePackage( packageDescr ) ;
mergePackage( this.pkg,
packageDescr );
} else {
this.pkg = newPackage( packageDescr );
}
//only try to compile if there are no parse errors
if ( !hasErrors() ) {
//iterate and compile
for ( final Iterator it = packageDescr.getFunctions().iterator(); it.hasNext(); ) {
addFunction( (FunctionDescr) it.next() );
}
//iterate and compile
for ( final Iterator it = packageDescr.getRules().iterator(); it.hasNext(); ) {
addRule( (RuleDescr) it.next() );
}
}
if ( this.generatedClassList.size() > 0 ) {
this.compileAll();
}
}
private void validatePackageName(final PackageDescr packageDescr) {
if ( packageDescr.getName() == null || "".equals( packageDescr.getName() ) ) {
throw new MissingPackageNameException( "Missing package name for rule package." );
}
}
private void validateUniqueRuleNames(final PackageDescr packageDescr) {
Set names = new HashSet();
for ( Iterator iter = packageDescr.getRules().iterator(); iter.hasNext(); ) {
RuleDescr rule = (RuleDescr) iter.next();
String name = rule.getName();
if ( names.contains( name ) ) {
this.results.add( new ParserError( "Duplicate rule name: " + name,
rule.getLine(),
rule.getColumn() ) );
}
names.add( name );
}
}
private Package newPackage(final PackageDescr packageDescr) {
final Package pkg = new Package( packageDescr.getName(),
this.configuration.getClassLoader() );
this.packageStoreWrapper = new PackageStore( pkg.getPackageCompilationData() );
mergePackage( pkg,
packageDescr );
return pkg;
}
private void mergePackage(final Package pkg,
final PackageDescr packageDescr) {
final List imports = packageDescr.getImports();
for ( final Iterator it = imports.iterator(); it.hasNext(); ) {
pkg.addImport( (String) it.next() );
}
final TypeResolver typeResolver = new ClassTypeResolver( imports,
pkg.getPackageCompilationData().getClassLoader() );
final Map globals = packageDescr.getGlobals();
for ( final Iterator it = globals.keySet().iterator(); it.hasNext(); ) {
final String identifier = (String) it.next();
final String className = (String) globals.get( identifier );
Class clazz;
try {
clazz = typeResolver.resolveType( className );
pkg.addGlobal( identifier,
clazz );
} catch ( final ClassNotFoundException e ) {
new GlobalError( identifier );
}
}
}
/**
* This adds a compile "task" for when the compiler of
* semantics (JCI) is called later on with compileAll()\
* which actually does the compiling.
* The ErrorHandler is required to map the errors back to the
* element that caused it.
*/
private void addClassCompileTask(final String className,
final String text,
final MemoryResourceReader src,
ErrorHandler handler) {
String fileName = className.replace( '.',
'/' ) + ".java";
src.add( fileName,
text.getBytes() );
this.errorHandlers.put( fileName,
handler );
this.generatedClassList.add( className );
}
private void addFunction(final FunctionDescr functionDescr) {
final FunctionBuilder buidler = new FunctionBuilder();
addClassCompileTask( this.pkg.getName() + "." + ucFirst( functionDescr.getName() ),
buidler.build( this.pkg,
functionDescr ),
this.src,
new FunctionErrorHandler( functionDescr,
"Function Compilation error" ) );
}
private void addRule(final RuleDescr ruleDescr) {
final String ruleClassName = getUniqueLegalName( this.pkg.getName(),
ruleDescr.getName(),
"java",
this.src );
ruleDescr.SetClassName( ucFirst( ruleClassName ) );
final RuleBuilder builder = new RuleBuilder( getTypeResolver(),
classFieldExtractorCache );
builder.build( this.pkg,
ruleDescr );
this.results.addAll( builder.getErrors() );
final Rule rule = builder.getRule();
// Check if there is any code to compile. If so compile it.
if ( builder.getRuleClass() != null ) {
addRuleSemantics( builder,
rule,
ruleDescr );
}
this.pkg.addRule( rule );
}
/**
* @return a Type resolver, lazily.
* If one does not exist yet, it will be initialised.
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -