Clover coverage report - Drools - 2.0-rc2
Coverage timestamp: Wed May 11 2005 07:12:26 BST
file stats: LOC: 337   Methods: 5
NCLOC: 269   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
JavaScriptEvaluator.java 87.5% 93.2% 100% 92.3%
coverage coverage
 1    package org.drools.semantics.java;
 2   
 3    import java.io.IOException;
 4    import java.io.StringReader;
 5    import java.lang.reflect.Method;
 6    import java.util.ArrayList;
 7    import java.util.HashSet;
 8    import java.util.Iterator;
 9    import java.util.List;
 10    import java.util.Map;
 11    import java.util.Set;
 12    import java.util.StringTokenizer;
 13   
 14    import org.codehaus.janino.DebuggingInformation;
 15    import org.codehaus.janino.EvaluatorBase;
 16    import org.codehaus.janino.Java;
 17    import org.codehaus.janino.Mod;
 18    import org.codehaus.janino.Parser;
 19    import org.codehaus.janino.Scanner;
 20    import org.codehaus.janino.Location;
 21    import org.codehaus.janino.Java.CompileException;
 22    import org.codehaus.janino.Parser.ParseException;
 23    import org.codehaus.janino.Scanner.ScanException;
 24    import org.codehaus.janino.util.PrimitiveWrapper;
 25   
 26    import org.drools.rule.Declaration;
 27    import org.drools.semantics.base.ClassObjectType;
 28    import org.drools.spi.Importer;
 29    import org.drools.spi.ObjectType;
 30   
 31    public class JavaScriptEvaluator extends EvaluatorBase
 32    {
 33   
 34    private final Method method;
 35   
 36  207 public Method getMethod()
 37    {
 38  207 return this.method;
 39    }
 40   
 41  209 public JavaScriptEvaluator(String code,
 42    String className,
 43    Class interfaceToImplement,
 44    String[] parameterNames,
 45    Declaration[] declarations,
 46    Importer importer,
 47    Map applicationData,
 48    Class baseClass,
 49    ClassLoader classLoader) throws Scanner.ScanException,
 50    Parser.ParseException,
 51    Java.CompileException,
 52    IOException,
 53    ClassNotFoundException
 54    {
 55  209 super( classLoader );
 56   
 57  209 Scanner scanner = new Scanner( null,
 58    new StringReader( code ) );
 59   
 60  209 Method[] methods = interfaceToImplement.getDeclaredMethods( );
 61  0 if ( methods.length != 1 ) throw new RuntimeException( "Interface \"" + interfaceToImplement + "\" must declare exactly one method" );
 62  209 Method methodToImplement = methods[0];
 63  209 String methodName = methodToImplement.getName( );
 64  209 Class[] parameterTypes = methodToImplement.getParameterTypes( );
 65   
 66  0 if ( parameterNames.length != parameterTypes.length ) throw new RuntimeException( "Lengths of \"parameterNames\" and \"parameterTypes\" do not match" );
 67   
 68    // Create a temporary compilation unit.
 69  209 Java.CompilationUnit compilationUnit = new Java.CompilationUnit( scanner.peek( ).getLocation( ).getFileName( ) );
 70   
 71    // Parse import declarations.
 72  209 this.parseImportDeclarations( compilationUnit,
 73    scanner );
 74   
 75    // Create class, method and block.
 76  209 Java.Block block = this.addClassMethodBlockDeclaration( scanner.peek( ).getLocation( ), // location
 77    compilationUnit, // compilationUnit
 78    className, // className
 79    baseClass, // optionalExtendedType
 80    new Class[]{interfaceToImplement}, // implementedTypes
 81    false, // staticMethod
 82    methodToImplement.getReturnType( ), // returnType
 83    methodName, // methodName
 84    parameterNames, // parameterNames
 85    parameterTypes, // parameterTypes
 86    methodToImplement.getExceptionTypes( ) );// thrownExceptions
 87   
 88    //make a copy as we will be adding app data declaration imports
 89    //but do not want to feed that back into the main import cache
 90  209 Set imports = new HashSet( importer.getImports( ) );
 91   
 92    // Parse block statements.
 93  209 Parser parser = new Parser( scanner );
 94   
 95    // block.addStatement(
 96   
 97  209 addDeclarations( scanner,
 98    block,
 99    declarations,
 100    imports );
 101  209 addAppData( scanner,
 102    block,
 103    applicationData,
 104    imports);
 105   
 106  209 Location loc = scanner.peek( ).getLocation( );
 107   
 108   
 109  209 Iterator it = imports.iterator( );
 110  209 String type;
 111  209 List list;
 112  209 StringTokenizer st;
 113  209 String token;
 114  209 boolean importOnDemand;
 115  209 while ( it.hasNext( ) )
 116    {
 117  309 importOnDemand = false;
 118  309 list = new ArrayList( );
 119  309 type = (String) it.next( );
 120  309 st = new StringTokenizer( type,
 121    "." );
 122  309 while ( st.hasMoreTokens( ) )
 123    {
 124  1565 token = st.nextToken( );
 125  1565 if ( !token.equals( "*" ) )
 126    {
 127  1543 list.add( token );
 128    }
 129    else
 130    {
 131  22 importOnDemand = true;
 132    }
 133    }
 134  309 if ( importOnDemand )
 135    {
 136  22 compilationUnit.addImportDeclaration( new Java.TypeImportOnDemandDeclaration( loc,
 137    (String[]) list.toArray( new String[list.size( )] ) ) );
 138    }
 139    else
 140    {
 141  287 compilationUnit.addImportDeclaration( new Java.SingleTypeImportDeclaration( loc,
 142    (String[]) list.toArray( new String[list.size( )] ) ) );
 143    }
 144    }
 145   
 146  209 while ( !scanner.peek( ).isEOF( ) )
 147    {
 148  341 block.addStatement( parser.parseBlockStatement( block ) );
 149    }
 150   
 151    // do not remove comments, usefull for debugging
 152    // UnparseVisitor.unparse(compilationUnit, new BufferedWriter( new
 153    // OutputStreamWriter(System.err)));
 154   
 155    // Compile and load it.
 156  208 Class c;
 157    //try
 158    //{
 159  208 c = this.compileAndLoad( compilationUnit,
 160    DebuggingInformation.ALL,
 161    className );
 162    //}
 163    //catch ( Exception e )
 164    //{
 165    //e.printStackTrace();
 166    //throw new RuntimeException( );
 167    //}
 168   
 169    // Find script method by name.
 170  207 try
 171    {
 172  207 this.method = c.getMethod( methodName,
 173    parameterTypes );
 174    }
 175    catch ( NoSuchMethodException ex )
 176    {
 177  0 throw new RuntimeException( ex.toString( ) );
 178    }
 179   
 180  0 if ( this.method == null ) throw new RuntimeException( "Method \"" + methodName + "\" not found" );
 181    }
 182   
 183  209 private void addAppData(Scanner scanner,
 184    Java.Block block,
 185    Map appData,
 186    Set imports )
 187    {
 188  209 Set keys = appData.keySet( );
 189  209 Iterator it = keys.iterator( );
 190  209 String key;
 191  209 Class clazz;
 192  209 String type;
 193  209 int nestedClassPosition;
 194   
 195  209 while ( it.hasNext( ) )
 196    {
 197  8 key = (String) it.next( );
 198  8 clazz = (Class) appData.get( key );
 199   
 200  8 type = clazz.getName( );
 201  8 nestedClassPosition = type.indexOf( '$' );
 202   
 203  8 if ( nestedClassPosition != -1 )
 204    {
 205  3 type = type.substring( 0,
 206    nestedClassPosition );
 207    }
 208   
 209  8 imports.add( type );
 210   
 211  8 Location loc = scanner.peek( ).getLocation( );
 212   
 213  8 Java.VariableDeclarator[] variables = new Java.VariableDeclarator[]{ // variableDeclarators
 214    new Java.VariableDeclarator( loc, // location
 215    key, // name
 216    0, // brackets
 217    new Java.Cast( loc, // location
 218    this.classToType( loc,
 219    clazz ), // targetType
 220    new Java.MethodInvocation( loc, // location
 221    block, // enclosingScope
 222    new Java.AmbiguousName( loc,
 223    block,
 224    new String[]{"applicationData"} ),
 225    "get", // methodName
 226    new Java.Rvalue[]{new Java.Literal( loc,
 227    key )} ) ) )};
 228   
 229  8 block.addStatement( new Java.LocalVariableDeclarationStatement( loc, // location
 230    block, // declaringBock
 231    Mod.FINAL, // modifiers
 232    this.classToType( loc,
 233    clazz ), // type
 234    variables ) );
 235    }
 236    }
 237   
 238  209 private void addDeclarations(Scanner scanner,
 239    Java.Block block,
 240    Declaration[] declarations,
 241    Set imports)
 242    {
 243  209 ObjectType objectType;
 244  209 Class clazz;
 245  209 String identifier;
 246  209 Declaration declaration;
 247   
 248  209 String type;
 249  209 int nestedClassPosition;
 250   
 251  209 for ( int i = 0; i < declarations.length; i++ )
 252    {
 253  373 declaration = declarations[i];
 254  373 identifier = declaration.getIdentifier( );
 255  373 objectType = declaration.getObjectType( );
 256   
 257  373 clazz = ((ClassObjectType) objectType).getType( );
 258   
 259  373 type = clazz.getName( );
 260  373 nestedClassPosition = type.indexOf( '$' );
 261   
 262  373 if ( nestedClassPosition != -1 )
 263    {
 264  23 type = type.substring( 0,
 265    nestedClassPosition );
 266    }
 267   
 268  373 imports.add( type );
 269   
 270  373 Location loc = scanner.peek( ).getLocation( );
 271   
 272  373 Java.VariableDeclarator[] variables = new Java.VariableDeclarator[]{ // variableDeclarators
 273    new Java.VariableDeclarator( loc, // location
 274    identifier, // name
 275    0, // brackets
 276    new Java.Cast( loc, // location
 277    this.classToType( loc,
 278    clazz ), // targetType
 279    new Java.MethodInvocation( loc, // location
 280    block, // enclosingScope
 281    new Java.AmbiguousName( loc,
 282    block,
 283    new String[]{"tuple"} ),
 284    "get", // methodName
 285    new Java.Rvalue[]{new Java.ArrayAccessExpression( loc,
 286    new Java.AmbiguousName( loc,
 287    block,
 288    new String[]{"decls"} ),
 289    new Java.ConstantValue( loc,
 290    PrimitiveWrapper.wrap( i ) ) )} ) ) )};
 291   
 292  373 block.addStatement( new Java.LocalVariableDeclarationStatement( loc, // location
 293    block, // declaringBock
 294    Mod.FINAL, // modifiers
 295    this.classToType( loc,
 296    clazz ), // type
 297    variables ) );
 298    }
 299   
 300    }
 301   
 302  209 public static Object compile(String block,
 303    String className,
 304    Class interfaceToImplement,
 305    String[] parameterNames,
 306    Declaration[] declarations,
 307    Importer importer,
 308    Map applicationData,
 309    Class baseClass,
 310    ClassLoader classLoader) throws ScanException, ParseException, CompileException, IOException, ClassNotFoundException
 311    {
 312  209 JavaScriptEvaluator scriptEvaluator = new JavaScriptEvaluator( block,
 313    className,
 314    interfaceToImplement,
 315    parameterNames,
 316    declarations,
 317    importer,
 318    applicationData,
 319    baseClass,
 320    classLoader );
 321   
 322  207 try
 323    {
 324  207 return scriptEvaluator.getMethod( ).getDeclaringClass( ).newInstance( );
 325    }
 326    catch ( InstantiationException e )
 327    {
 328    // SNO - Declared class is always non-abstract.
 329  0 throw new RuntimeException( e.toString( ) );
 330    }
 331    catch ( IllegalAccessException e )
 332    {
 333    // SNO - interface methods are always PUBLIC.
 334  0 throw new RuntimeException( e.toString( ) );
 335    }
 336    }
 337    }