if ( newPkg.hasTraitRegistry() ) {
getTraitRegistry().merge( newPkg.getTraitRegistry() );
}
Package pkg = this.pkgs.get( newPkg.getName() );
if ( pkg == null ) {
pkg = new Package( newPkg.getName() );
// @TODO we really should have a single root cache
pkg.setClassFieldAccessorCache( this.classFieldAccessorCache );
pkgs.put( pkg.getName(),
pkg );
}
// first merge anything related to classloader re-wiring
pkg.getDialectRuntimeRegistry().merge( newPkg.getDialectRuntimeRegistry(),
this.rootClassLoader,
true );
}
// Add all Type Declarations, this has to be done first incase packages cross reference each other during build process.
for ( Package newPkg : clonedPkgs ) {
// we have to do this before the merging, as it does some classloader resolving
String lastType = null;
try {
// Add the type declarations to the RuleBase
if ( newPkg.getTypeDeclarations() != null ) {
JavaDialectRuntimeData runtime = ((JavaDialectRuntimeData) newPkg.getDialectRuntimeRegistry().getDialectData( "java" ));
// add type declarations
for ( TypeDeclaration newDecl : newPkg.getTypeDeclarations().values() ) {
lastType = newDecl.getTypeClassName();
TypeDeclaration typeDeclaration = this.classTypeDeclaration.get( newDecl.getTypeClassName() );
if ( typeDeclaration == null ) {
String className = newDecl.getTypeClassName();
byte [] def = runtime.getClassDefinition(convertClassToResourcePath(className));
Class<?> definedKlass = registerAndLoadTypeDefinition( className, def );
if ( definedKlass == null && typeDeclaration.isNovel() ) {
throw new RuntimeException( "Registering null bytes for class " + className );
}
if (newDecl.getTypeClassDef() == null) {
newDecl.setTypeClassDef( new ClassDefinition() );
}
newDecl.getTypeClassDef().setDefinedClass( definedKlass );
newDecl.setTypeClass( definedKlass );
this.classTypeDeclaration.put( className, newDecl );
typeDeclaration = newDecl;
} else {
Class<?> definedKlass = typeDeclaration.getTypeClass();
newDecl.getTypeClassDef().setDefinedClass( definedKlass );
newDecl.setTypeClass( definedKlass );
mergeTypeDeclarations( typeDeclaration,
newDecl );
}
// update existing OTNs
updateDependentTypes( newPkg,
typeDeclaration );
}
}
} catch (ClassNotFoundException e) {
throw new RuntimeDroolsException( "unable to resolve Type Declaration class '" + lastType + "'", e );
}
}
// now iterate again, this time onBeforeExecute will handle any wiring or cloader re-creating that needs to be done as part of the merge
for (Package newPkg : clonedPkgs) {
Package pkg = this.pkgs.get( newPkg.getName() );
// this needs to go here, as functions will set a java dialect to dirty
if (newPkg.getFunctions() != null) {
for (Map.Entry<String, Function> entry : newPkg.getFunctions().entrySet()) {
pkg.addFunction( entry.getValue() );
}
}
pkg.getDialectRuntimeRegistry().onBeforeExecute();
// with the classloader recreated for all byte[] classes, we should now merge and wire any new accessors
pkg.getClassFieldAccessorStore().merge( newPkg.getClassFieldAccessorStore() );
}
for (Package newPkg : clonedPkgs) {
Package pkg = this.pkgs.get( newPkg.getName() );
// now merge the new package into the existing one
mergePackage( pkg,
newPkg );