@Test public void cookClassesCachingTest() throws Exception { String codeBlock1 = "public boolean processRow() {\n" + " return true;\n" + "}\n\n"; String codeBlock2 = "public boolean processRow() {\n" + " + " return true;\n" + "}\n\n"; UserDefinedJavaClassMeta userDefinedJavaClassMeta1 = new UserDefinedJavaClassMeta(); UserDefinedJavaClassDef userDefinedJavaClassDef1 = new UserDefinedJavaClassDef( UserDefinedJavaClassDef.ClassType.NORMAL_CLASS, "MainClass", codeBlock1 ); StepMeta stepMeta = Mockito.mock( StepMeta.class ); Mockito.when( stepMeta.getName() ).thenReturn( "User Defined Java Class" ); userDefinedJavaClassMeta1.setParentStepMeta( stepMeta ); UserDefinedJavaClassMeta userDefinedJavaClassMetaSpy = Mockito.spy( userDefinedJavaClassMeta1 ); Class<?> clazz1 = userDefinedJavaClassMetaSpy.cookClass( userDefinedJavaClassDef1 ); Class<?> clazz2 = userDefinedJavaClassMetaSpy.cookClass( userDefinedJavaClassDef1 ); Assert.assertTrue( clazz1 == clazz2 ); UserDefinedJavaClassMeta userDefinedJavaClassMeta2 = new UserDefinedJavaClassMeta(); UserDefinedJavaClassDef userDefinedJavaClassDef2 = new UserDefinedJavaClassDef( UserDefinedJavaClassDef.ClassType.NORMAL_CLASS, "AnotherClass", codeBlock2 ); StepMeta stepMeta2 = Mockito.mock( StepMeta.class ); Mockito.when( stepMeta2.getName() ).thenReturn( "Another UDJC" ); userDefinedJavaClassMeta2.setParentStepMeta( stepMeta2 ); UserDefinedJavaClassMeta userDefinedJavaClassMeta2Spy = Mockito.spy( userDefinedJavaClassMeta2 ); Class<?> clazz3 = userDefinedJavaClassMeta2Spy.cookClass( userDefinedJavaClassDef2 ); Assert.assertTrue( clazz3 != clazz1 ); }
@VisibleForTesting Class<?> cookClass( UserDefinedJavaClassDef def ) throws CompileException, ParseException, ScanException, IOException, RuntimeException, KettleStepException { String checksum = def.getChecksum(); Class<?> rtn = UserDefinedJavaClassMeta.classCache.getIfPresent( checksum ); if ( rtn != null ) { return rtn; } if ( Thread.currentThread().getContextClassLoader() == null ) { Thread.currentThread().setContextClassLoader( this.getClass().getClassLoader() ); } ClassBodyEvaluator cbe = new ClassBodyEvaluator(); cbe.setParentClassLoader( Thread.currentThread().getContextClassLoader() ); cbe.setClassName( def.getClassName() ); StringReader sr; if ( def.isTransformClass() ) { cbe.setExtendedType( TransformClassBase.class ); sr = new StringReader( def.getTransformedSource() ); } else { sr = new StringReader( def.getSource() ); } cbe.setDefaultImports( new String[] { "org.pentaho.di.trans.steps.userdefinedjavaclass.*", "org.pentaho.di.trans.step.*", "org.pentaho.di.core.row.*", "org.pentaho.di.core.*", "org.pentaho.di.core.exception.*" } ); cbe.cook( new Scanner( null, sr ) ); rtn = cbe.getClazz(); UserDefinedJavaClassMeta.classCache.put( checksum, rtn ); return rtn; }
UserDefinedJavaClassMeta extends BaseStepMeta implements StepMetaInterface { @VisibleForTesting Class<?> cookClass( UserDefinedJavaClassDef def ) throws CompileException, ParseException, ScanException, IOException, RuntimeException, KettleStepException { String checksum = def.getChecksum(); Class<?> rtn = UserDefinedJavaClassMeta.classCache.getIfPresent( checksum ); if ( rtn != null ) { return rtn; } if ( Thread.currentThread().getContextClassLoader() == null ) { Thread.currentThread().setContextClassLoader( this.getClass().getClassLoader() ); } ClassBodyEvaluator cbe = new ClassBodyEvaluator(); cbe.setParentClassLoader( Thread.currentThread().getContextClassLoader() ); cbe.setClassName( def.getClassName() ); StringReader sr; if ( def.isTransformClass() ) { cbe.setExtendedType( TransformClassBase.class ); sr = new StringReader( def.getTransformedSource() ); } else { sr = new StringReader( def.getSource() ); } cbe.setDefaultImports( new String[] { "org.pentaho.di.trans.steps.userdefinedjavaclass.*", "org.pentaho.di.trans.step.*", "org.pentaho.di.core.row.*", "org.pentaho.di.core.*", "org.pentaho.di.core.exception.*" } ); cbe.cook( new Scanner( null, sr ) ); rtn = cbe.getClazz(); UserDefinedJavaClassMeta.classCache.put( checksum, rtn ); return rtn; } }
UserDefinedJavaClassMeta extends BaseStepMeta implements StepMetaInterface { @VisibleForTesting Class<?> cookClass( UserDefinedJavaClassDef def ) throws CompileException, ParseException, ScanException, IOException, RuntimeException, KettleStepException { String checksum = def.getChecksum(); Class<?> rtn = UserDefinedJavaClassMeta.classCache.getIfPresent( checksum ); if ( rtn != null ) { return rtn; } if ( Thread.currentThread().getContextClassLoader() == null ) { Thread.currentThread().setContextClassLoader( this.getClass().getClassLoader() ); } ClassBodyEvaluator cbe = new ClassBodyEvaluator(); cbe.setParentClassLoader( Thread.currentThread().getContextClassLoader() ); cbe.setClassName( def.getClassName() ); StringReader sr; if ( def.isTransformClass() ) { cbe.setExtendedType( TransformClassBase.class ); sr = new StringReader( def.getTransformedSource() ); } else { sr = new StringReader( def.getSource() ); } cbe.setDefaultImports( new String[] { "org.pentaho.di.trans.steps.userdefinedjavaclass.*", "org.pentaho.di.trans.step.*", "org.pentaho.di.core.row.*", "org.pentaho.di.core.*", "org.pentaho.di.core.exception.*" } ); cbe.cook( new Scanner( null, sr ) ); rtn = cbe.getClazz(); UserDefinedJavaClassMeta.classCache.put( checksum, rtn ); return rtn; } UserDefinedJavaClassMeta(); }
UserDefinedJavaClassMeta extends BaseStepMeta implements StepMetaInterface { @VisibleForTesting Class<?> cookClass( UserDefinedJavaClassDef def ) throws CompileException, ParseException, ScanException, IOException, RuntimeException, KettleStepException { String checksum = def.getChecksum(); Class<?> rtn = UserDefinedJavaClassMeta.classCache.getIfPresent( checksum ); if ( rtn != null ) { return rtn; } if ( Thread.currentThread().getContextClassLoader() == null ) { Thread.currentThread().setContextClassLoader( this.getClass().getClassLoader() ); } ClassBodyEvaluator cbe = new ClassBodyEvaluator(); cbe.setParentClassLoader( Thread.currentThread().getContextClassLoader() ); cbe.setClassName( def.getClassName() ); StringReader sr; if ( def.isTransformClass() ) { cbe.setExtendedType( TransformClassBase.class ); sr = new StringReader( def.getTransformedSource() ); } else { sr = new StringReader( def.getSource() ); } cbe.setDefaultImports( new String[] { "org.pentaho.di.trans.steps.userdefinedjavaclass.*", "org.pentaho.di.trans.step.*", "org.pentaho.di.core.row.*", "org.pentaho.di.core.*", "org.pentaho.di.core.exception.*" } ); cbe.cook( new Scanner( null, sr ) ); rtn = cbe.getClazz(); UserDefinedJavaClassMeta.classCache.put( checksum, rtn ); return rtn; } UserDefinedJavaClassMeta(); @SuppressWarnings( "unchecked" ) void cookClasses(); TransformClassBase newChildInstance( UserDefinedJavaClass parent, UserDefinedJavaClassMeta meta, UserDefinedJavaClassData data ); List<FieldInfo> getFieldInfo(); void replaceFields( List<FieldInfo> fields ); List<UserDefinedJavaClassDef> getDefinitions(); void replaceDefinitions( List<UserDefinedJavaClassDef> definitions ); void loadXML( Node stepnode, List<DatabaseMeta> databases, IMetaStore metaStore ); Object clone(); void setDefault(); @Override StepIOMetaInterface getStepIOMeta(); @Override void searchInfoAndTargetSteps( List<StepMeta> steps ); void getFields( RowMetaInterface row, String originStepname, RowMetaInterface[] info, StepMeta nextStep,
    VariableSpace space, Repository repository, IMetaStore metaStore ); String getXML(); void readRep( Repository rep, IMetaStore metaStore, ObjectId id_step, List<DatabaseMeta> databases ); void saveRep( Repository rep, IMetaStore metaStore, ObjectId id_transformation, ObjectId id_step ); void check( List<CheckResultInterface> remarks, TransMeta transMeta, StepMeta stepinfo,
    RowMetaInterface prev, String[] input, String[] output, RowMetaInterface info, VariableSpace space,
    Repository repository, IMetaStore metaStore ); StepInterface getStep( StepMeta stepMeta, StepDataInterface stepDataInterface, int cnr,
    TransMeta transMeta, Trans trans ); StepDataInterface getStepData(); boolean supportsErrorHandling(); boolean isClearingResultFields(); void setClearingResultFields( boolean clearingResultFields ); List<StepDefinition> getInfoStepDefinitions(); void setInfoStepDefinitions( List<StepDefinition> infoStepDefinitions ); List<StepDefinition> getTargetStepDefinitions(); void setTargetStepDefinitions( List<StepDefinition> targetStepDefinitions ); @Override boolean excludeFromRowLayoutVerification(); List<UsageParameter> getUsageParameters(); void setUsageParameters( List<UsageParameter> usageParameters ); }
UserDefinedJavaClassMeta extends BaseStepMeta implements StepMetaInterface { @VisibleForTesting Class<?> cookClass( UserDefinedJavaClassDef def ) throws CompileException, ParseException, ScanException, IOException, RuntimeException, KettleStepException { String checksum = def.getChecksum(); Class<?> rtn = UserDefinedJavaClassMeta.classCache.getIfPresent( checksum ); if ( rtn != null ) { return rtn; } if ( Thread.currentThread().getContextClassLoader() == null ) { Thread.currentThread().setContextClassLoader( this.getClass().getClassLoader() ); } ClassBodyEvaluator cbe = new ClassBodyEvaluator(); cbe.setParentClassLoader( Thread.currentThread().getContextClassLoader() ); cbe.setClassName( def.getClassName() ); StringReader sr; if ( def.isTransformClass() ) { cbe.setExtendedType( TransformClassBase.class ); sr = new StringReader( def.getTransformedSource() ); } else { sr = new StringReader( def.getSource() ); } cbe.setDefaultImports( new String[] { "org.pentaho.di.trans.steps.userdefinedjavaclass.*", "org.pentaho.di.trans.step.*", "org.pentaho.di.core.row.*", "org.pentaho.di.core.*", "org.pentaho.di.core.exception.*" } ); cbe.cook( new Scanner( null, sr ) ); rtn = cbe.getClazz(); UserDefinedJavaClassMeta.classCache.put( checksum, rtn ); return rtn; } UserDefinedJavaClassMeta(); @SuppressWarnings( "unchecked" ) void cookClasses(); TransformClassBase newChildInstance( UserDefinedJavaClass parent, UserDefinedJavaClassMeta meta, UserDefinedJavaClassData data ); List<FieldInfo> getFieldInfo(); void replaceFields( List<FieldInfo> fields ); List<UserDefinedJavaClassDef> getDefinitions(); void replaceDefinitions( List<UserDefinedJavaClassDef> definitions ); void loadXML( Node stepnode, List<DatabaseMeta> databases, IMetaStore metaStore ); Object clone(); void setDefault(); @Override StepIOMetaInterface getStepIOMeta(); @Override void searchInfoAndTargetSteps( List<StepMeta> steps ); void getFields( RowMetaInterface row, String originStepname, RowMetaInterface[] info, StepMeta nextStep,
    VariableSpace space, Repository repository, IMetaStore metaStore ); String getXML(); void readRep( Repository rep, IMetaStore metaStore, ObjectId id_step, List<DatabaseMeta> databases ); void saveRep( Repository rep, IMetaStore metaStore, ObjectId id_transformation, ObjectId id_step ); void check( List<CheckResultInterface> remarks, TransMeta transMeta, StepMeta stepinfo,
    RowMetaInterface prev, String[] input, String[] output, RowMetaInterface info, VariableSpace space,
    Repository repository, IMetaStore metaStore ); StepInterface getStep( StepMeta stepMeta, StepDataInterface stepDataInterface, int cnr,
    TransMeta transMeta, Trans trans ); StepDataInterface getStepData(); boolean supportsErrorHandling(); boolean isClearingResultFields(); void setClearingResultFields( boolean clearingResultFields ); List<StepDefinition> getInfoStepDefinitions(); void setInfoStepDefinitions( List<StepDefinition> infoStepDefinitions ); List<StepDefinition> getTargetStepDefinitions(); void setTargetStepDefinitions( List<StepDefinition> targetStepDefinitions ); @Override boolean excludeFromRowLayoutVerification(); List<UsageParameter> getUsageParameters(); void setUsageParameters( List<UsageParameter> usageParameters ); public Class<TransformClassBase> cookedTransformClass; public List<Exception> cookErrors; }