📄 packagebuilder.java
字号:
private TypeResolver getTypeResolver() {
if ( this.typeResolver == null ) {
typeResolver = new ClassTypeResolver( pkg.getImports(),
pkg.getPackageCompilationData().getClassLoader() );
// make an automatic import for the current package
typeResolver.addImport( pkg.getName() + ".*" );
typeResolver.addImport( "java.lang.*" );
}
return this.typeResolver;
}
/**
* @deprecated Do not use for compiling rules. Do a whole package at a time.
*/
public void compileRule(final RuleBuilder builder,
final Rule rule,
final RuleDescr ruleDescr) {
addRuleSemantics( builder,
rule,
ruleDescr );
this.compileAll();
}
/**
* This will setup the semantic components of the rule for compiling later on.
* It will not actually call the compiler
*/
private void addRuleSemantics(final RuleBuilder builder,
final Rule rule,
final RuleDescr ruleDescr) {
// The compilation result is for th entire rule, so difficult to associate with any descr
addClassCompileTask( this.pkg.getName() + "." + ruleDescr.getClassName(),
builder.getRuleClass(),
this.src,
new RuleErrorHandler( ruleDescr,
rule,
"Rule Compilation error" ) );
for ( final Iterator it = builder.getInvokers().keySet().iterator(); it.hasNext(); ) {
final String className = (String) it.next();
// Check if an invoker - returnvalue, predicate, eval or consequence has been associated
// If so we add it to the PackageCompilationData as it will get wired up on compilation
final Object invoker = builder.getInvokerLookups().get( className );
if ( invoker != null ) {
this.pkg.getPackageCompilationData().putInvoker( className,
invoker );
}
final String text = (String) builder.getInvokers().get( className );
//System.out.println( className + ":\n" + text );
final PatternDescr descr = (PatternDescr) builder.getDescrLookups().get( className );
addClassCompileTask( className,
text,
this.src,
new RuleInvokerErrorHandler( descr,
rule,
"Unable to generate rule invoker." ) );
}
}
/**
* @return The compiled package. The package may contain errors, which you can report on
* by calling getErrors or printErrors. If you try to add an invalid package (or rule)
* to a RuleBase, you will get a runtime exception.
*
* Compiled packages are serializable.
*/
public Package getPackage() {
if ( hasErrors() ) {
this.pkg.setError( this.printErrors() );
}
return this.pkg;
}
/**
* This actually triggers the compiling of all the resources.
* Errors are mapped back to the element that originally generated the semantic
* code.
*/
private void compileAll() {
String[] classes = new String[this.generatedClassList.size()];
this.generatedClassList.toArray( classes );
final CompilationResult result = this.compiler.compile( classes,
src,
this.packageStoreWrapper,
this.pkg.getPackageCompilationData().getClassLoader() );
//this will sort out the errors based on what class/file they happened in
if ( result.getErrors().length > 0 ) {
for ( int i = 0; i < result.getErrors().length; i++ ) {
CompilationProblem err = result.getErrors()[i];
ErrorHandler handler = (ErrorHandler) this.errorHandlers.get( err.getFileName() );
if (handler instanceof RuleErrorHandler) {
RuleErrorHandler rh = (RuleErrorHandler) handler;
}
handler.addError( err );
}
Collection errors = this.errorHandlers.values();
for ( Iterator iter = errors.iterator(); iter.hasNext(); ) {
ErrorHandler handler = (ErrorHandler) iter.next();
if (handler.isInError()) {
if ( !(handler instanceof RuleInvokerErrorHandler) ) {
this.results.add( handler.getError() );
} else {
//we don't really want to report invoker errors.
//mostly as they can happen when there is a syntax error in the RHS
//and otherwise, it is a programmatic error in drools itself.
System.err.println( "Warning: An error occurred compiling a semantic invoker. Errors should have been reported elsewhere.");
}
}
}
}
}
/** This will return true if there were errors in the package building and compiling phase */
public boolean hasErrors() {
return this.results.size() > 0;
}
/**
* @return A list of Error objects that resulted from building and compiling the package.
*/
public DroolsError[] getErrors() {
return (DroolsError[]) this.results.toArray( new DroolsError[this.results.size()] );
}
/**
* This will pretty print the errors (from getErrors())
* into lines.
*/
public String printErrors() {
final StringBuffer buf = new StringBuffer();
for ( final Iterator iter = this.results.iterator(); iter.hasNext(); ) {
final DroolsError err = (DroolsError) iter.next();
buf.append( err.getMessage() );
buf.append( "\n" );
}
return buf.toString();
}
/**
* Takes a given name and makes sure that its legal and doesn't already exist. If the file exists it increases counter appender untill it is unique.
*
* @param packageName
* @param name
* @param ext
* @return
*/
private String getUniqueLegalName(final String packageName,
final String name,
final String ext,
final ResourceReader src) {
// replaces all non alphanumeric or $ chars with _
String newName = "Rule_" + name.replaceAll( "[^\\w$]",
"_" );
// make sure the class name does not exist, if it does increase the counter
int counter = -1;
boolean exists = true;
while ( exists ) {
counter++;
final String fileName = packageName.replaceAll( "\\.",
"/" ) + newName + "_" + counter + ext;
exists = src.isAvailable( fileName );
}
// we have duplicate file names so append counter
if ( counter >= 0 ) {
newName = newName + "_" + counter;
}
return newName;
}
private void loadCompiler() {
switch ( configuration.getCompiler() ) {
case PackageBuilderConfiguration.JANINO : {
if ( !"1.4".equals( configuration.getJavaLanguageLevel() ) ) throw new RuntimeDroolsException( "Incompatible Java language level with selected compiler" );
compiler = JavaCompilerFactory.getInstance().createCompiler( "janino" );
break;
}
case PackageBuilderConfiguration.ECLIPSE :
default : {
EclipseJavaCompilerSettings eclipseSettings = new EclipseJavaCompilerSettings();
eclipseSettings.getMap().put( "org.eclipse.jdt.core.compiler.codegen.targetPlatform",
configuration.getJavaLanguageLevel() );
eclipseSettings.getMap().put( "org.eclipse.jdt.core.compiler.source",
configuration.getJavaLanguageLevel() );
compiler = new EclipseJavaCompiler( eclipseSettings );
break;
}
}
}
private String ucFirst(final String name) {
return name.toUpperCase().charAt( 0 ) + name.substring( 1 );
}
public static class MissingPackageNameException extends IllegalArgumentException {
private static final long serialVersionUID = 4056984379574366454L;
public MissingPackageNameException(final String message) {
super( message );
}
}
/**
* This is the super of the error handlers.
* Each error handler knows how to report a compile error of its type, should it happen.
* This is needed, as the compiling is done as one
* hit at the end, and we need to be able to work out what rule/ast element
* caused the error.
*
* An error handler it created for each class task that is queued to be compiled.
* This doesn't mean an error has occurred, it just means it *may* occur
* in the future and we need to be able to map it back to the AST element
* that originally spawned the code to be compiled.
*/
public abstract static class ErrorHandler {
private List errors = new ArrayList();
protected String message;
private boolean inError = false;
/** This needes to be checked if there is infact an error */
public boolean isInError() {
return inError;
}
public void addError(CompilationProblem err) {
this.errors.add( err );
this.inError = true;
}
/**
*
* @return A DroolsError object populated as appropriate,
* should the unthinkable happen and this need to be reported.
*/
public abstract DroolsError getError();
/**
* We must use an error of JCI problem objects.
* If there are no problems, null is returned.
* These errors are placed in the DroolsError instances.
* Its not 1 to 1 with reported errors.
*/
protected CompilationProblem[] collectCompilerProblems() {
if ( errors.size() == 0 ) {
return null;
} else {
CompilationProblem[] list = new CompilationProblem[errors.size()];
errors.toArray( list );
return list;
}
}
}
public static class RuleErrorHandler extends ErrorHandler {
private PatternDescr descr;
private Rule rule;
public RuleErrorHandler(PatternDescr ruleDescr,
Rule rule,
String message) {
this.descr = ruleDescr;
this.rule = rule;
this.message = message;
}
public DroolsError getError() {
return new RuleError( rule,
descr,
collectCompilerProblems(),
message );
}
}
/**
* There isn't much point in reporting invoker errors, as
* they are no help.
*/
public static class RuleInvokerErrorHandler extends RuleErrorHandler {
public RuleInvokerErrorHandler(PatternDescr ruleDescr,
Rule rule,
String message) {
super( ruleDescr,
rule,
message );
}
}
public static class FunctionErrorHandler extends ErrorHandler {
private FunctionDescr descr;
public FunctionErrorHandler(FunctionDescr functionDescr,
String message) {
this.descr = functionDescr;
this.message = message;
}
public DroolsError getError() {
return new FunctionError( descr,
collectCompilerProblems(),
message );
}
}
private static JavaCompiler cachedJavaCompiler = null;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -