Skip to content

Commit

Permalink
[BZ-1063255] store generated classes in kproject jar when building it…
Browse files Browse the repository at this point in the history
… with the kie-maven-plugin
  • Loading branch information
mariofusco committed Feb 10, 2014
1 parent c3094c2 commit c572148
Show file tree
Hide file tree
Showing 7 changed files with 237 additions and 123 deletions.
Expand Up @@ -22,6 +22,7 @@
public interface ResourceStore {

void write( final String pResourceName, final byte[] pResourceData );
void write( final String pResourceName, final byte[] pResourceData, boolean createFolder );
byte[] read( final String pResourceName );
//FIXME: return the result of the remove
void remove( final String pResourceName );
Expand Down
Expand Up @@ -85,6 +85,11 @@ public void write(String pResourceName, byte[] pResourceData) {
projectClassLoader.defineClass(convertResourceToClassName(pResourceName), pResourceName, pResourceData);
}

@Override
public void write(final String resourceName, final byte[] clazzData, boolean createFolder) {
write(resourceName, clazzData);
}

@Override
public byte[] read(String pResourceName) {
return projectClassLoader.getBytecode(pResourceName);
Expand Down
@@ -1,44 +1,28 @@
package org.drools.compiler.kie.builder.impl;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.drools.compiler.builder.impl.KnowledgeBuilderImpl;
import org.drools.compiler.commons.jci.compilers.CompilationResult;
import org.drools.compiler.commons.jci.compilers.EclipseJavaCompiler;
import org.drools.compiler.commons.jci.compilers.EclipseJavaCompilerSettings;
import org.drools.compiler.commons.jci.problems.CompilationProblem;
import org.drools.compiler.commons.jci.readers.DiskResourceReader;
import org.drools.compiler.commons.jci.readers.ResourceReader;
import org.drools.compiler.compiler.PackageRegistry;
import org.drools.compiler.compiler.io.memory.MemoryFileSystem;
import org.drools.compiler.kie.builder.impl.KieModuleCache.CompDataEntry;
import org.drools.compiler.kie.builder.impl.KieModuleCache.CompilationData;
import org.drools.compiler.kie.builder.impl.KieModuleCache.KModuleCache;
import org.drools.compiler.kproject.ReleaseIdImpl;
import org.drools.compiler.kproject.models.KieModuleModelImpl;
import org.drools.compiler.kproject.xml.PomModel;
import org.drools.core.builder.conf.impl.ResourceConfigurationImpl;
import org.drools.core.factmodel.ClassDefinition;
import org.drools.core.rule.JavaDialectRuntimeData;
import org.drools.core.rule.KieModuleMetaInfo;
import org.drools.core.rule.TypeDeclaration;
import org.drools.core.rule.TypeMetaInfo;
import org.drools.core.util.StringUtils;
import org.kie.api.KieBaseConfiguration;
import org.kie.api.KieServices;
Expand All @@ -51,9 +35,6 @@
import org.kie.api.builder.model.KieBaseModel;
import org.kie.api.builder.model.KieModuleModel;
import org.kie.api.builder.model.KieSessionModel;
import org.kie.api.definition.KiePackage;
import org.kie.api.definition.rule.Rule;
import org.kie.api.definition.type.FactType;
import org.kie.api.io.Resource;
import org.kie.api.io.ResourceConfiguration;
import org.kie.api.io.ResourceType;
Expand All @@ -62,7 +43,6 @@
import org.kie.internal.builder.InternalKieBuilder;
import org.kie.internal.builder.KieBuilderSet;

import com.google.protobuf.ByteString;
import org.kie.internal.io.ResourceTypeImpl;

public class KieBuilderImpl
Expand Down Expand Up @@ -195,7 +175,7 @@ public KieBuilder buildAll() {
compileJavaClasses(kProject.getClassLoader());

if ( buildKieProject( kModule, results, kProject ) ) {
writeKieModuleMetaInfo( generateKieModuleMetaInfo() );
new KieMetaInfoBuilder(trgMfs, kModule).writeKieModuleMetaInfo();
}
}
return this;
Expand All @@ -210,115 +190,14 @@ Collection<String> getModifiedResourcesSinceLastMark() {
}

void updateKieModuleMetaInfo() {
writeKieModuleMetaInfo( generateKieModuleMetaInfo() );
}

private KieModuleMetaInfo generateKieModuleMetaInfo() {
// TODO: I think this method is wrong because it is only inspecting packages that are included
// in at least one kbase, but I believe it should inspect all packages, even if not included in
// any kbase, as they could be included in the future
Map<String, TypeMetaInfo> typeInfos = new HashMap<String, TypeMetaInfo>();
Map<String, Set<String>> rulesPerPackage = new HashMap<String, Set<String>>();

KieModuleModel kieModuleModel = kModule.getKieModuleModel();
for ( String kieBaseName : kieModuleModel.getKieBaseModels().keySet() ) {
KnowledgeBuilderImpl kBuilder = (KnowledgeBuilderImpl) kModule.getKnowledgeBuilderForKieBase( kieBaseName );
Map<String, PackageRegistry> pkgRegistryMap = kBuilder.getPackageBuilder().getPackageRegistry();

KModuleCache.Builder _kmoduleCacheBuilder = createCacheBuilder();
CompilationData.Builder _compData = createCompilationData();

for ( KiePackage kPkg : kBuilder.getKnowledgePackages() ) {
PackageRegistry pkgRegistry = pkgRegistryMap.get( kPkg.getName() );
JavaDialectRuntimeData runtimeData = (JavaDialectRuntimeData) pkgRegistry.getDialectRuntimeRegistry().getDialectData( "java" );

List<String> types = new ArrayList<String>();
for ( FactType factType : kPkg.getFactTypes() ) {
Class< ? > typeClass = ((ClassDefinition) factType).getDefinedClass();
TypeDeclaration typeDeclaration = pkgRegistry.getPackage().getTypeDeclaration( typeClass );
if ( typeDeclaration != null ) {
typeInfos.put( typeClass.getName(), new TypeMetaInfo(typeDeclaration) );
}

String className = factType.getName();
String internalName = className.replace('.', '/') + ".class";
byte[] bytes = runtimeData.getBytecode(internalName);
if (bytes != null) {
trgMfs.write( internalName, bytes, true );
}
types.add( internalName );
}

Set<String> rules = rulesPerPackage.get( kPkg.getName() );
if( rules == null ) {
rules = new HashSet<String>();
}
for ( Rule rule : kPkg.getRules() ) {
if( !rules.contains( rule.getName() ) ) {
rules.add(rule.getName());
}
}
if (!rules.isEmpty()) {
rulesPerPackage.put(kPkg.getName(), rules);
}

addToCompilationData(_compData, runtimeData, types);
}

_kmoduleCacheBuilder.addCompilationData( _compData.build() );
writeCompilationDataToTrg( _kmoduleCacheBuilder.build(), kieBaseName );
}
return new KieModuleMetaInfo(typeInfos, rulesPerPackage);
}

private KModuleCache.Builder createCacheBuilder() {
KModuleCache.Builder _kmoduleCacheBuilder = KModuleCache.newBuilder();
return _kmoduleCacheBuilder;
}

private CompilationData.Builder createCompilationData() {
// Create compilation data cache
CompilationData.Builder _cdata = KieModuleCache.CompilationData.newBuilder()
.setDialect("java");
return _cdata;
}

private void addToCompilationData(CompilationData.Builder _cdata,
JavaDialectRuntimeData runtimeData,
List<String> types) {
for ( Entry<String, byte[]> entry : runtimeData.getStore().entrySet() ) {
if ( !types.contains( entry.getKey() ) ) {
CompDataEntry _entry = KieModuleCache.CompDataEntry.newBuilder()
.setId( entry.getKey() )
.setData( ByteString.copyFrom( entry.getValue() ) )
.build();
_cdata.addEntry( _entry );
}
}
}

private void writeCompilationDataToTrg(KModuleCache _kmoduleCache,
String kieBaseName) {
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
KieModuleCacheHelper.writeToStreamWithHeader( out, _kmoduleCache );
trgMfs.write( getCompilationCachePath( releaseId, kieBaseName ), out.toByteArray(), true );
} catch ( IOException e ) {
// what to do here?
}
new KieMetaInfoBuilder(trgMfs, kModule).writeKieModuleMetaInfo();
}

public static String getCompilationCachePath(ReleaseId releaseId,
String kbaseName) {
return ((ReleaseIdImpl) releaseId).getCompilationCachePathPrefix() + kbaseName.replace( '.', '/' ) + "/kbase.cache";
}

private void writeKieModuleMetaInfo(KieModuleMetaInfo info) {
trgMfs.write( KieModuleModelImpl.KMODULE_INFO_JAR_PATH,
info.marshallMetaInfos().getBytes(),
true );
}

public static boolean buildKieModule(InternalKieModule kModule,
ResultsImpl messages ) {
return buildKieProject(kModule, messages, new KieModuleKieProject( kModule ));
Expand Down
@@ -0,0 +1,136 @@
package org.drools.compiler.kie.builder.impl;

import com.google.protobuf.ByteString;
import org.drools.compiler.builder.impl.KnowledgeBuilderImpl;
import org.drools.compiler.commons.jci.stores.ResourceStore;
import org.drools.compiler.compiler.PackageRegistry;
import org.drools.compiler.kproject.models.KieModuleModelImpl;
import org.drools.core.factmodel.ClassDefinition;
import org.drools.core.rule.JavaDialectRuntimeData;
import org.drools.core.rule.KieModuleMetaInfo;
import org.drools.core.rule.TypeDeclaration;
import org.drools.core.rule.TypeMetaInfo;
import org.kie.api.builder.model.KieModuleModel;
import org.kie.api.definition.KiePackage;
import org.kie.api.definition.rule.Rule;
import org.kie.api.definition.type.FactType;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class KieMetaInfoBuilder {

private final ResourceStore trgMfs;
private final InternalKieModule kModule;

public KieMetaInfoBuilder(ResourceStore trgMfs, InternalKieModule kModule) {
this.trgMfs = trgMfs;
this.kModule = kModule;
}

public void writeKieModuleMetaInfo() {
KieModuleMetaInfo info = generateKieModuleMetaInfo();
trgMfs.write( KieModuleModelImpl.KMODULE_INFO_JAR_PATH,
info.marshallMetaInfos().getBytes(),
true );
}

private KieModuleMetaInfo generateKieModuleMetaInfo() {
// TODO: I think this method is wrong because it is only inspecting packages that are included
// in at least one kbase, but I believe it should inspect all packages, even if not included in
// any kbase, as they could be included in the future
Map<String, TypeMetaInfo> typeInfos = new HashMap<String, TypeMetaInfo>();
Map<String, Set<String>> rulesPerPackage = new HashMap<String, Set<String>>();

KieModuleModel kieModuleModel = kModule.getKieModuleModel();
for ( String kieBaseName : kieModuleModel.getKieBaseModels().keySet() ) {
KnowledgeBuilderImpl kBuilder = (KnowledgeBuilderImpl) kModule.getKnowledgeBuilderForKieBase( kieBaseName );
Map<String, PackageRegistry> pkgRegistryMap = kBuilder.getPackageBuilder().getPackageRegistry();

KieModuleCache.KModuleCache.Builder _kmoduleCacheBuilder = createCacheBuilder();
KieModuleCache.CompilationData.Builder _compData = createCompilationData();

for ( KiePackage kPkg : kBuilder.getKnowledgePackages() ) {
PackageRegistry pkgRegistry = pkgRegistryMap.get( kPkg.getName() );
JavaDialectRuntimeData runtimeData = (JavaDialectRuntimeData) pkgRegistry.getDialectRuntimeRegistry().getDialectData( "java" );

List<String> types = new ArrayList<String>();
for ( FactType factType : kPkg.getFactTypes() ) {
Class< ? > typeClass = ((ClassDefinition) factType).getDefinedClass();
TypeDeclaration typeDeclaration = pkgRegistry.getPackage().getTypeDeclaration( typeClass );
if ( typeDeclaration != null ) {
typeInfos.put( typeClass.getName(), new TypeMetaInfo(typeDeclaration) );
}

String className = factType.getName();
String internalName = className.replace('.', '/') + ".class";
byte[] bytes = runtimeData.getBytecode(internalName);
if (bytes != null) {
trgMfs.write( internalName, bytes, true );
}
types.add( internalName );
}

Set<String> rules = rulesPerPackage.get( kPkg.getName() );
if( rules == null ) {
rules = new HashSet<String>();
}
for ( Rule rule : kPkg.getRules() ) {
if( !rules.contains( rule.getName() ) ) {
rules.add(rule.getName());
}
}
if (!rules.isEmpty()) {
rulesPerPackage.put(kPkg.getName(), rules);
}

addToCompilationData(_compData, runtimeData, types);
}

_kmoduleCacheBuilder.addCompilationData( _compData.build() );
writeCompilationDataToTrg( _kmoduleCacheBuilder.build(), kieBaseName );
}
return new KieModuleMetaInfo(typeInfos, rulesPerPackage);
}

private KieModuleCache.KModuleCache.Builder createCacheBuilder() {
return KieModuleCache.KModuleCache.newBuilder();
}

private KieModuleCache.CompilationData.Builder createCompilationData() {
// Create compilation data cache
return KieModuleCache.CompilationData.newBuilder().setDialect("java");
}

private void addToCompilationData(KieModuleCache.CompilationData.Builder _cdata,
JavaDialectRuntimeData runtimeData,
List<String> types) {
for ( Map.Entry<String, byte[]> entry : runtimeData.getStore().entrySet() ) {
if ( !types.contains( entry.getKey() ) ) {
KieModuleCache.CompDataEntry _entry = KieModuleCache.CompDataEntry.newBuilder()
.setId( entry.getKey() )
.setData( ByteString.copyFrom(entry.getValue()) )
.build();
_cdata.addEntry( _entry );
}
}
}

private void writeCompilationDataToTrg(KieModuleCache.KModuleCache _kmoduleCache,
String kieBaseName) {
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
KieModuleCacheHelper.writeToStreamWithHeader( out, _kmoduleCache );
String compilatonDataPath = "META-INF/" + kieBaseName.replace( '.', '/' ) + "/kbase.cache";
trgMfs.write( compilatonDataPath, out.toByteArray(), true );
} catch ( IOException e ) {
// what to do here?
}
}
}
Expand Up @@ -53,6 +53,12 @@ public void write(final String resourceName,
}
}

public void write(final String resourceName,
final byte[] clazzData,
boolean createFolder) {
write(resourceName, clazzData);
}

public byte[] read(final String resourceName) {
byte[] clazz = null;
try {
Expand Down
Expand Up @@ -6,6 +6,8 @@
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.drools.compiler.kie.builder.impl.InternalKieModule;
import org.drools.compiler.kie.builder.impl.KieMetaInfoBuilder;
import org.kie.api.KieServices;
import org.kie.api.builder.KieModule;
import org.kie.api.builder.KieRepository;
Expand Down Expand Up @@ -95,6 +97,8 @@ public void execute() throws MojoExecutionException, MojoFailureException {
getLog().error(error.toString());
}
throw new MojoFailureException("Build failed!");
} else {
new KieMetaInfoBuilder(new DiskResourceStore(outputDirectory), (InternalKieModule)kModule).writeKieModuleMetaInfo();
}
} finally {
Thread.currentThread().setContextClassLoader(contextClassLoader);
Expand Down

0 comments on commit c572148

Please sign in to comment.