conf.setClassLoader( context.getPackageBuilder().getRootClassLoader() );
// first compilation is for verification only
// @todo proper source file name
final ParserContext parserContext1 = new ParserContext( conf );
if ( localTypes != null ) {
for ( Entry entry : localTypes.entrySet() ) {
parserContext1.addInput( (String) entry.getKey(),
(Class) entry.getValue() );
}
}
if ( availableIdentifiers.getThisClass() != null ) {
parserContext1.addInput( "this",
availableIdentifiers.getThisClass() );
}
if ( availableIdentifiers.getOperators() != null ) {
for ( Entry<String, EvaluatorWrapper> opEntry : availableIdentifiers.getOperators().entrySet() ) {
parserContext1.addInput( opEntry.getKey(), opEntry.getValue().getClass() );
}
}
parserContext1.setStrictTypeEnforcement( false );
parserContext1.setStrongTyping( false );
parserContext1.setInterceptors( dialect.getInterceptors() );
Class< ? > returnType;
try {
returnType = MVEL.analyze( expr,
parserContext1 );
} catch ( Exception e ) {
BaseDescr base = (context instanceof RuleBuildContext) ? ((RuleBuildContext)context).getRuleDescr() : context.getParentDescr();
DialectUtil.copyErrorLocation(e, context.getParentDescr());
context.addError( new DescrBuildError( base,
context.getParentDescr(),
null,
"Unable to Analyse Expression " + expr + ":\n" + e.getMessage() ) );
return null;
}
Set<String> requiredInputs = new HashSet<String>();
requiredInputs.addAll( parserContext1.getInputs().keySet() );
HashMap<String, Class< ? >> variables = (HashMap<String, Class< ? >>) ((Map) parserContext1.getVariables());
if ( localTypes != null ) {
for ( String str : localTypes.keySet() ) {
// we have to do this due to mvel regressions on detecting true local vars
variables.remove( str );
}
}
// MVEL includes direct fields of context object in non-strict mode. so we need to strip those
if ( availableIdentifiers.getThisClass() != null ) {
for ( Iterator<String> it = requiredInputs.iterator(); it.hasNext(); ) {
if ( PropertyTools.getFieldOrAccessor( availableIdentifiers.getThisClass(),
it.next() ) != null ) {
it.remove();
}
}
}
// now, set the required input types and compile again
final ParserContext parserContext2 = new ParserContext( conf );
parserContext2.setStrictTypeEnforcement( true );
parserContext2.setStrongTyping( true );
parserContext2.setInterceptors( dialect.getInterceptors() );
for ( String str : requiredInputs ) {
Class< ? > cls = availableIdentifiers.getDeclrClasses().get( str );
if ( cls != null ) {
parserContext2.addInput( str,
cls );
continue;
}
cls = availableIdentifiers.getGlobals().get( str );
if ( cls != null ) {
parserContext2.addInput( str,
cls );
continue;
}
cls = availableIdentifiers.getOperators().keySet().contains( str ) ? context.getConfiguration().getComponentFactory().getExpressionProcessor().getEvaluatorWrapperClass() : null;
if ( cls != null ) {
parserContext2.addInput( str,
cls );
continue;
}
if ( str.equals( contextIndeifier ) ) {
parserContext2.addInput( contextIndeifier,
kcontextClass );
} else if ( str.equals( "kcontext" ) ) {
parserContext2.addInput( "kcontext",
kcontextClass );
}
if ( str.equals( "rule" ) ) {
parserContext2.addInput( "rule",
Rule.class );
}
if ( localTypes != null ) {
cls = localTypes.get( str );
if ( cls != null ) {
parserContext2.addInput( str,
cls );
}
}
}
if ( availableIdentifiers.getThisClass() != null ) {
parserContext2.addInput( "this",
availableIdentifiers.getThisClass() );
}
boolean typesafe = context.isTypesafe();
try {
returnType = MVEL.analyze( expr,
parserContext2 );
typesafe = true;
} catch ( Exception e ) {
// is this an error, or can we fall back to non-typesafe mode?
if ( typesafe ) {
BaseDescr base = (context instanceof RuleBuildContext) ? ((RuleBuildContext)context).getRuleDescr() : context.getParentDescr();
DialectUtil.copyErrorLocation(e, context.getParentDescr());
context.addError( new DescrBuildError( base,
context.getParentDescr(),
null,
"Unable to Analyse Expression " + expr + ":\n" + e.getMessage() ) );
return null;
}
}
if ( typesafe ) {
requiredInputs = new HashSet<String>();
requiredInputs.addAll( parserContext2.getInputs().keySet() );
requiredInputs.addAll( variables.keySet() );
variables = (HashMap<String, Class< ? >>) ((Map) parserContext2.getVariables());
if ( localTypes != null ) {
for ( String str : localTypes.keySet() ) {
// we have to do this due to mvel regressions on detecting true local vars
variables.remove( str );
}