From c572148c16d1000f8948c7183e1d5daf29d349e3 Mon Sep 17 00:00:00 2001 From: mariofusco Date: Mon, 10 Feb 2014 12:44:34 +0100 Subject: [PATCH] [BZ-1063255] store generated classes in kproject jar when building it with the kie-maven-plugin --- .../commons/jci/stores/ResourceStore.java | 1 + .../compiler/ProjectJavaCompiler.java | 5 + .../kie/builder/impl/KieBuilderImpl.java | 125 +--------------- .../kie/builder/impl/KieMetaInfoBuilder.java | 136 ++++++++++++++++++ .../builder/dialect/java/PackageStore.java | 6 + .../java/org/kie/maven/plugin/BuildMojo.java | 4 + .../kie/maven/plugin/DiskResourceStore.java | 83 +++++++++++ 7 files changed, 237 insertions(+), 123 deletions(-) create mode 100644 drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/KieMetaInfoBuilder.java create mode 100644 kie-maven-plugin/src/main/java/org/kie/maven/plugin/DiskResourceStore.java diff --git a/drools-compiler/src/main/java/org/drools/compiler/commons/jci/stores/ResourceStore.java b/drools-compiler/src/main/java/org/drools/compiler/commons/jci/stores/ResourceStore.java index 18e5a936cbf..1bc6f3b8ff2 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/commons/jci/stores/ResourceStore.java +++ b/drools-compiler/src/main/java/org/drools/compiler/commons/jci/stores/ResourceStore.java @@ -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 ); diff --git a/drools-compiler/src/main/java/org/drools/compiler/compiler/ProjectJavaCompiler.java b/drools-compiler/src/main/java/org/drools/compiler/compiler/ProjectJavaCompiler.java index e1b8b87d27e..e0245092f1e 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/compiler/ProjectJavaCompiler.java +++ b/drools-compiler/src/main/java/org/drools/compiler/compiler/ProjectJavaCompiler.java @@ -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); diff --git a/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/KieBuilderImpl.java b/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/KieBuilderImpl.java index d235820e8b1..d1e07386057 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/KieBuilderImpl.java +++ b/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/KieBuilderImpl.java @@ -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; @@ -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; @@ -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 @@ -195,7 +175,7 @@ public KieBuilder buildAll() { compileJavaClasses(kProject.getClassLoader()); if ( buildKieProject( kModule, results, kProject ) ) { - writeKieModuleMetaInfo( generateKieModuleMetaInfo() ); + new KieMetaInfoBuilder(trgMfs, kModule).writeKieModuleMetaInfo(); } } return this; @@ -210,102 +190,7 @@ Collection 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 typeInfos = new HashMap(); - Map> rulesPerPackage = new HashMap>(); - - KieModuleModel kieModuleModel = kModule.getKieModuleModel(); - for ( String kieBaseName : kieModuleModel.getKieBaseModels().keySet() ) { - KnowledgeBuilderImpl kBuilder = (KnowledgeBuilderImpl) kModule.getKnowledgeBuilderForKieBase( kieBaseName ); - Map 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 types = new ArrayList(); - 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 rules = rulesPerPackage.get( kPkg.getName() ); - if( rules == null ) { - rules = new HashSet(); - } - 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 types) { - for ( Entry 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, @@ -313,12 +198,6 @@ public static String getCompilationCachePath(ReleaseId releaseId, 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 )); diff --git a/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/KieMetaInfoBuilder.java b/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/KieMetaInfoBuilder.java new file mode 100644 index 00000000000..ee051c4f1f9 --- /dev/null +++ b/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/KieMetaInfoBuilder.java @@ -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 typeInfos = new HashMap(); + Map> rulesPerPackage = new HashMap>(); + + KieModuleModel kieModuleModel = kModule.getKieModuleModel(); + for ( String kieBaseName : kieModuleModel.getKieBaseModels().keySet() ) { + KnowledgeBuilderImpl kBuilder = (KnowledgeBuilderImpl) kModule.getKnowledgeBuilderForKieBase( kieBaseName ); + Map 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 types = new ArrayList(); + 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 rules = rulesPerPackage.get( kPkg.getName() ); + if( rules == null ) { + rules = new HashSet(); + } + 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 types) { + for ( Map.Entry 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? + } + } +} diff --git a/drools-compiler/src/main/java/org/drools/compiler/rule/builder/dialect/java/PackageStore.java b/drools-compiler/src/main/java/org/drools/compiler/rule/builder/dialect/java/PackageStore.java index f325039120d..49dec24ae6a 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/rule/builder/dialect/java/PackageStore.java +++ b/drools-compiler/src/main/java/org/drools/compiler/rule/builder/dialect/java/PackageStore.java @@ -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 { diff --git a/kie-maven-plugin/src/main/java/org/kie/maven/plugin/BuildMojo.java b/kie-maven-plugin/src/main/java/org/kie/maven/plugin/BuildMojo.java index 7030298f50e..725355c6d1e 100644 --- a/kie-maven-plugin/src/main/java/org/kie/maven/plugin/BuildMojo.java +++ b/kie-maven-plugin/src/main/java/org/kie/maven/plugin/BuildMojo.java @@ -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; @@ -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); diff --git a/kie-maven-plugin/src/main/java/org/kie/maven/plugin/DiskResourceStore.java b/kie-maven-plugin/src/main/java/org/kie/maven/plugin/DiskResourceStore.java new file mode 100644 index 00000000000..14aa1429a14 --- /dev/null +++ b/kie-maven-plugin/src/main/java/org/kie/maven/plugin/DiskResourceStore.java @@ -0,0 +1,83 @@ +package org.kie.maven.plugin; + +import org.drools.compiler.commons.jci.stores.ResourceStore; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import static org.drools.core.util.IoUtils.readBytesFromInputStream; + +public class DiskResourceStore implements ResourceStore { + private final File root; + + public DiskResourceStore(File root) { + this.root = root; + } + + @Override + public void write(String pResourceName, byte[] pResourceData) { + write(pResourceName, pResourceData, false); + } + + @Override + public void write(String pResourceName, byte[] pResourceData, boolean createFolder) { + File file = new File(getFilePath(pResourceName)); + if (createFolder) { + File dir = file.getParentFile(); + if (!dir.exists()) { + dir.mkdirs(); + } + } + + FileOutputStream fos = null; + try { + fos = new FileOutputStream(file); + fos.write(pResourceData); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + if (fos != null) { + try { + fos.close(); + } catch (IOException e) { } + } + } + } + + @Override + public byte[] read(String pResourceName) { + FileInputStream fis = null; + try { + fis = new FileInputStream(getFilePath(pResourceName)); + return readBytesFromInputStream(fis); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + if (fis != null) { + try { + fis.close(); + } catch (IOException e) { } + } + } + } + + @Override + public void remove(String pResourceName) { + File file = new File(getFilePath(pResourceName)); + if (file.exists()) { + file.delete(); + } + } + + private String getFilePath(String pResourceName) { + return root.getAbsolutePath() + File.separator + pResourceName; + } +}