From c8e09e2056c54ead97bce4386a25b222154223b1 Mon Sep 17 00:00:00 2001 From: kedzie Date: Thu, 12 Jun 2014 18:34:44 -0500 Subject: [PATCH] [DROOLS-729] Android support * load either default or dex classloaders, depending on environment, for generated classes * maven plugin for pre-serializing knowledge packages during buildtime --- .../kie/builder/impl/ClasspathKieProject.java | 2 +- .../core/base/ClassFieldAccessorCache.java | 11 +- .../core/base/ClassFieldAccessorFactory.java | 2 +- .../core/common/ProjectClassLoader.java | 26 +++- .../core/rule/JavaDialectRuntimeData.java | 30 +++-- .../builder/dialect/asm/ClassGenerator.java | 17 ++- .../core/util/ByteArrayClassLoader.java | 24 ++++ .../java/org/drools/core/util/ClassUtils.java | 96 ++++++++++++-- .../java/org/drools/core/util/Drools.java | 2 +- .../java/org/drools/core/util/IoUtils.java | 3 + .../java/org/drools/core/util/MemoryUtil.java | 28 +++-- kie-maven-plugin/pom.xml | 119 ++++++++++++++++++ ...jectDependenciesComponentConfigurator.java | 97 ++++++++++++++ .../org/kie/maven/plugin/SerializeMojo.java | 93 ++++++++++++++ .../kie/maven/plugin/TouchResourcesMojo.java | 92 ++++++++++++++ .../plugin/BuildMojoIntegrationTest.java | 56 +++++++++ .../src/test/projects/kjar-1/pom.xml | 53 ++++++++ .../main/java/org/kie/sample/model/Fire.java | 35 ++++++ .../main/java/org/kie/sample/model/Room.java | 51 ++++++++ .../java/org/kie/sample/model/Sprinkler.java | 60 +++++++++ .../main/resources/FireAlarmKBase/alarm.drl | 3 + .../main/resources/FireAlarmKBase/rules.drl | 23 ++++ .../main/resources/FireAlarmKBase/rules2.drl | 29 +++++ .../kjar-1/src/main/resources/KBase1/decA.drl | 4 + .../kjar-1/src/main/resources/KBase1/decB.drl | 4 + .../kjar-1/src/main/resources/KBase1/rule.drl | 6 + .../src/main/resources/META-INF/kmodule.xml | 9 ++ .../java/org/kie/kproject/KProjectTest.java | 52 ++++++++ 28 files changed, 979 insertions(+), 48 deletions(-) create mode 100644 drools-core/src/main/java/org/drools/core/util/ByteArrayClassLoader.java create mode 100644 kie-maven-plugin/src/main/java/org/kie/maven/plugin/IncludeProjectDependenciesComponentConfigurator.java create mode 100644 kie-maven-plugin/src/main/java/org/kie/maven/plugin/SerializeMojo.java create mode 100644 kie-maven-plugin/src/main/java/org/kie/maven/plugin/TouchResourcesMojo.java create mode 100644 kie-maven-plugin/src/test/java/org/kie/maven/plugin/BuildMojoIntegrationTest.java create mode 100644 kie-maven-plugin/src/test/projects/kjar-1/pom.xml create mode 100644 kie-maven-plugin/src/test/projects/kjar-1/src/main/java/org/kie/sample/model/Fire.java create mode 100644 kie-maven-plugin/src/test/projects/kjar-1/src/main/java/org/kie/sample/model/Room.java create mode 100644 kie-maven-plugin/src/test/projects/kjar-1/src/main/java/org/kie/sample/model/Sprinkler.java create mode 100644 kie-maven-plugin/src/test/projects/kjar-1/src/main/resources/FireAlarmKBase/alarm.drl create mode 100644 kie-maven-plugin/src/test/projects/kjar-1/src/main/resources/FireAlarmKBase/rules.drl create mode 100644 kie-maven-plugin/src/test/projects/kjar-1/src/main/resources/FireAlarmKBase/rules2.drl create mode 100644 kie-maven-plugin/src/test/projects/kjar-1/src/main/resources/KBase1/decA.drl create mode 100644 kie-maven-plugin/src/test/projects/kjar-1/src/main/resources/KBase1/decB.drl create mode 100644 kie-maven-plugin/src/test/projects/kjar-1/src/main/resources/KBase1/rule.drl create mode 100644 kie-maven-plugin/src/test/projects/kjar-1/src/main/resources/META-INF/kmodule.xml create mode 100644 kie-maven-plugin/src/test/projects/kjar-1/src/test/java/org/kie/kproject/KProjectTest.java diff --git a/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/ClasspathKieProject.java b/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/ClasspathKieProject.java index 9cacccb7605..670d9196c4d 100644 --- a/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/ClasspathKieProject.java +++ b/drools-compiler/src/main/java/org/drools/compiler/kie/builder/impl/ClasspathKieProject.java @@ -196,7 +196,7 @@ public static String getPomProperties(String urlPathToAdd) { rootPath = IoUtils.asSystemSpecificPath( rootPath, rootPath.lastIndexOf( ':' ) ); } - if ( urlPathToAdd.endsWith( ".jar" ) || urlPathToAdd.endsWith( "/content" ) ) { + if ( urlPathToAdd.endsWith( ".apk" ) || urlPathToAdd.endsWith( ".jar" ) || urlPathToAdd.endsWith( "/content" ) ) { pomProperties = getPomPropertiesFromZipFile(rootPath); } else { pomProperties = getPomPropertiesFromFileSystem(rootPath); diff --git a/drools-core/src/main/java/org/drools/core/base/ClassFieldAccessorCache.java b/drools-core/src/main/java/org/drools/core/base/ClassFieldAccessorCache.java index 30cbafe338d..79aa65c83ee 100644 --- a/drools-core/src/main/java/org/drools/core/base/ClassFieldAccessorCache.java +++ b/drools-core/src/main/java/org/drools/core/base/ClassFieldAccessorCache.java @@ -16,6 +16,8 @@ package org.drools.core.base; +import org.drools.core.util.ByteArrayClassLoader; +import org.drools.core.util.ClassUtils; import org.drools.core.util.asm.ClassFieldInspector; import java.security.ProtectionDomain; @@ -152,7 +154,10 @@ public CacheEntry(ClassLoader parentClassLoader) { if ( parentClassLoader == null ) { throw new RuntimeException( "ClassFieldAccessorFactory cannot have a null parent ClassLoader" ); } - this.byteArrayClassLoader = new ByteArrayClassLoader( parentClassLoader ); + this.byteArrayClassLoader = ClassUtils.isAndroid() ? + (ByteArrayClassLoader) ClassUtils.instantiateObject( + "org.drools.android.MultiDexClassLoader", null, parentClassLoader) : + new DefaultByteArrayClassLoader( parentClassLoader ); } public ByteArrayClassLoader getByteArrayClassLoader() { @@ -223,8 +228,8 @@ public ClassObjectType getClassObjectType(Class cls, } - public static class ByteArrayClassLoader extends ClassLoader { - public ByteArrayClassLoader(final ClassLoader parent) { + public static class DefaultByteArrayClassLoader extends ClassLoader implements ByteArrayClassLoader { + public DefaultByteArrayClassLoader(final ClassLoader parent) { super( parent ); } diff --git a/drools-core/src/main/java/org/drools/core/base/ClassFieldAccessorFactory.java b/drools-core/src/main/java/org/drools/core/base/ClassFieldAccessorFactory.java index 6888c2feb23..6fa6b08957c 100644 --- a/drools-core/src/main/java/org/drools/core/base/ClassFieldAccessorFactory.java +++ b/drools-core/src/main/java/org/drools/core/base/ClassFieldAccessorFactory.java @@ -16,7 +16,6 @@ package org.drools.core.base; -import org.drools.core.base.ClassFieldAccessorCache.ByteArrayClassLoader; import org.drools.core.base.ClassFieldAccessorCache.CacheEntry; import org.drools.core.base.extractors.BaseBooleanClassFieldReader; import org.drools.core.base.extractors.BaseBooleanClassFieldWriter; @@ -41,6 +40,7 @@ import org.drools.core.base.extractors.SelfReferenceClassFieldReader; import org.drools.core.common.InternalWorkingMemory; import org.drools.core.util.asm.ClassFieldInspector; +import org.drools.core.util.ByteArrayClassLoader; import org.mvel2.asm.ClassWriter; import org.mvel2.asm.Label; import org.mvel2.asm.MethodVisitor; diff --git a/drools-core/src/main/java/org/drools/core/common/ProjectClassLoader.java b/drools-core/src/main/java/org/drools/core/common/ProjectClassLoader.java index 72018130293..8d53756d747 100644 --- a/drools-core/src/main/java/org/drools/core/common/ProjectClassLoader.java +++ b/drools-core/src/main/java/org/drools/core/common/ProjectClassLoader.java @@ -1,5 +1,7 @@ package org.drools.core.common; +import org.drools.core.util.ClassUtils; + import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; @@ -130,7 +132,7 @@ protected Class loadClass(String name, boolean resolve) throws ClassNotFoundE return cls; } - private Class internalLoadClass(String name, boolean resolve) throws ClassNotFoundException { + Class internalLoadClass(String name, boolean resolve) throws ClassNotFoundException { if (CACHE_NON_EXISTING_CLASSES && nonExistingClasses.contains(name)) { throw dummyCFNE; } @@ -159,7 +161,7 @@ private Class loadType(String name, boolean resolve) throws ClassNotFoundExce return tryDefineType(name, cnfe); } - private Class tryDefineType(String name, ClassNotFoundException cnfe) throws ClassNotFoundException { + Class tryDefineType(String name, ClassNotFoundException cnfe) throws ClassNotFoundException { byte[] bytecode = getBytecode(convertClassToResourcePath(name)); if (bytecode == null) { if (CACHE_NON_EXISTING_CLASSES) { @@ -181,7 +183,7 @@ private Class defineType(String name, byte[] bytecode) { } if (typesClassLoader == null) { - typesClassLoader = new InternalTypesClassLoader(this); + typesClassLoader = makeClassLoader(); } Class clazz = typesClassLoader.defineClass(name, bytecode); definedTypes.put(name, new ClassBytecode(clazz, bytecode)); @@ -324,11 +326,23 @@ public void initFrom(ProjectClassLoader other) { nonExistingClasses.addAll(other.nonExistingClasses); } - private static class InternalTypesClassLoader extends ClassLoader { + private InternalTypesClassLoader makeClassLoader() { + return ClassUtils.isAndroid() ? + (InternalTypesClassLoader) ClassUtils.instantiateObject( + "org.drools.core.common.DexInternalTypesClassLoader", null, this) : + new DefaultInternalTypesClassLoader( this ); + } + + interface InternalTypesClassLoader { + Class defineClass(String name, byte[] bytecode); + Class loadType(String name, boolean resolve) throws ClassNotFoundException; + } + + private static class DefaultInternalTypesClassLoader extends ClassLoader implements InternalTypesClassLoader { private final ProjectClassLoader projectClassLoader; - private InternalTypesClassLoader(ProjectClassLoader projectClassLoader) { + private DefaultInternalTypesClassLoader(ProjectClassLoader projectClassLoader) { super(projectClassLoader.getParent()); this.projectClassLoader = projectClassLoader; } @@ -358,7 +372,7 @@ protected Class loadClass(String name, boolean resolve) throws ClassNotFoundE } } - private Class loadType(String name, boolean resolve) throws ClassNotFoundException { + public Class loadType(String name, boolean resolve) throws ClassNotFoundException { return super.loadClass(name, resolve); } } diff --git a/drools-core/src/main/java/org/drools/core/rule/JavaDialectRuntimeData.java b/drools-core/src/main/java/org/drools/core/rule/JavaDialectRuntimeData.java index 9bce92d0433..9ba2a3afa86 100644 --- a/drools-core/src/main/java/org/drools/core/rule/JavaDialectRuntimeData.java +++ b/drools-core/src/main/java/org/drools/core/rule/JavaDialectRuntimeData.java @@ -21,6 +21,7 @@ import org.drools.core.definitions.rule.impl.RuleImpl; import org.drools.core.spi.Constraint; import org.drools.core.spi.Wireable; +import org.drools.core.util.ClassUtils; import org.drools.core.util.KeyStoreHelper; import org.drools.core.util.StringUtils; import org.kie.internal.concurrent.ExecutorProviderFactory; @@ -74,7 +75,7 @@ public class JavaDialectRuntimeData private Map store; - private transient PackageClassLoader classLoader; + private transient ClassLoader classLoader; private transient ClassLoader rootClassLoader; @@ -238,8 +239,7 @@ private void checkSignature( final ObjectInput stream, public void onAdd( DialectRuntimeRegistry registry, ClassLoader rootClassLoader ) { this.rootClassLoader = rootClassLoader; - this.classLoader = new PackageClassLoader( this, - this.rootClassLoader ); + this.classLoader = makeClassLoader(); } public void onRemove() { @@ -280,18 +280,18 @@ private void wireInParallel(int wireListSize) throws Exception { } } - private static void wireAll(PackageClassLoader classLoader, Map invokerLookups, List wireList) throws ClassNotFoundException, InstantiationException, IllegalAccessException { + private static void wireAll(ClassLoader classLoader, Map invokerLookups, List wireList) throws ClassNotFoundException, InstantiationException, IllegalAccessException { for (String resourceName : wireList) { wire( classLoader, invokerLookups, convertResourceToClassName( resourceName ) ); } } private static class WiringExecutor implements Callable { - private final PackageClassLoader classLoader; + private final ClassLoader classLoader; private final Map invokerLookups; private final List wireList; - private WiringExecutor(PackageClassLoader classLoader, Map invokerLookups, List wireList) { + private WiringExecutor(ClassLoader classLoader, Map invokerLookups, List wireList) { this.classLoader = classLoader; this.invokerLookups = invokerLookups; this.wireList = wireList; @@ -476,15 +476,15 @@ public void wire( final String className ) throws ClassNotFoundException, Instan wire(className, getInvokers().get(className)); } - private static void wire( PackageClassLoader classLoader, Map invokerLookups, String className ) throws ClassNotFoundException, InstantiationException, IllegalAccessException { - wire( classLoader, className, invokerLookups.get( className ) ); + private static void wire( ClassLoader classLoader, Map invokerLookups, String className ) throws ClassNotFoundException, InstantiationException, IllegalAccessException { + wire( classLoader, className, invokerLookups.get(className) ); } public void wire( final String className, final Object invoker ) throws ClassNotFoundException, InstantiationException, IllegalAccessException { wire( classLoader, className, invoker ); } - private static void wire( PackageClassLoader classLoader, String className, Object invoker ) throws ClassNotFoundException, InstantiationException, IllegalAccessException { + private static void wire( ClassLoader classLoader, String className, Object invoker ) throws ClassNotFoundException, InstantiationException, IllegalAccessException { final Class clazz = classLoader.loadClass( className ); if (clazz != null) { @@ -523,8 +523,7 @@ public String[] list() { */ public void reload() { // drops the classLoader and adds a new one - this.classLoader = new PackageClassLoader( this, - this.rootClassLoader ); + this.classLoader = makeClassLoader(); // Wire up invokers try { @@ -613,6 +612,13 @@ public void removeClassDefinition( final String className ) { getClassDefinitions().remove( className ); } + private ClassLoader makeClassLoader() { + return ClassUtils.isAndroid() ? + (ClassLoader) ClassUtils.instantiateObject( + "org.drools.android.DexPackageClassLoader", null, this, this.rootClassLoader) + : new PackageClassLoader( this, this.rootClassLoader ); + } + /** * This is an Internal Drools Class */ @@ -621,7 +627,7 @@ public static class PackageClassLoader extends ClassLoader implements FastClassL protected JavaDialectRuntimeData store; private Set existingPackages = new ConcurrentSkipListSet(); - + public PackageClassLoader( JavaDialectRuntimeData store, ClassLoader rootClassLoader ) { super( rootClassLoader ); diff --git a/drools-core/src/main/java/org/drools/core/rule/builder/dialect/asm/ClassGenerator.java b/drools-core/src/main/java/org/drools/core/rule/builder/dialect/asm/ClassGenerator.java index 98654915c57..3a3738fde40 100644 --- a/drools-core/src/main/java/org/drools/core/rule/builder/dialect/asm/ClassGenerator.java +++ b/drools-core/src/main/java/org/drools/core/rule/builder/dialect/asm/ClassGenerator.java @@ -1,6 +1,9 @@ package org.drools.core.rule.builder.dialect.asm; +import org.drools.core.base.ClassFieldAccessorCache; import org.drools.core.base.TypeResolver; +import org.drools.core.util.ByteArrayClassLoader; +import org.drools.core.util.ClassUtils; import org.mvel2.asm.ClassWriter; import org.mvel2.asm.MethodVisitor; import org.mvel2.asm.Type; @@ -141,10 +144,16 @@ public byte[] generateBytecode() { private Class generateClass() { if (clazz == null) { byte[] bytecode = generateBytecode(); - try { - clazz = (Class) defineClassMethod.invoke(classLoader, className, bytecode, 0, bytecode.length); - } catch (Exception e) { - clazz = new InternalClassLoader(classLoader).defineClass(className, bytecode); + if (ClassUtils.isAndroid()) { + ByteArrayClassLoader cl = (ByteArrayClassLoader) + ClassUtils.instantiateObject("org.drools.android.MultiDexClassLoader", null, classLoader); + clazz = cl.defineClass(className, bytecode, null); + } else { + try { + clazz = (Class) defineClassMethod.invoke(classLoader, className, bytecode, 0, bytecode.length); + } catch (Exception e) { + clazz = new InternalClassLoader(classLoader).defineClass(className, bytecode); + } } } return clazz; diff --git a/drools-core/src/main/java/org/drools/core/util/ByteArrayClassLoader.java b/drools-core/src/main/java/org/drools/core/util/ByteArrayClassLoader.java new file mode 100644 index 00000000000..7b7a3f6ddee --- /dev/null +++ b/drools-core/src/main/java/org/drools/core/util/ByteArrayClassLoader.java @@ -0,0 +1,24 @@ +/* + * Copyright 2015 JBoss Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.drools.core.util; + +import java.security.ProtectionDomain; + +public interface ByteArrayClassLoader { + Class< ? > defineClass(final String name, + final byte[] bytes, + final ProtectionDomain domain); +} diff --git a/drools-core/src/main/java/org/drools/core/util/ClassUtils.java b/drools-core/src/main/java/org/drools/core/util/ClassUtils.java index ba936d059a3..f6dd793a1ec 100644 --- a/drools-core/src/main/java/org/drools/core/util/ClassUtils.java +++ b/drools-core/src/main/java/org/drools/core/util/ClassUtils.java @@ -28,6 +28,7 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -51,6 +52,8 @@ public final class ClassUtils { private static final ProtectionDomain PROTECTION_DOMAIN; + public static final boolean IS_ANDROID; + static { PROTECTION_DOMAIN = (ProtectionDomain) AccessController.doPrivileged( new PrivilegedAction() { @@ -58,10 +61,23 @@ public Object run() { return ClassLoaderUtil.class.getProtectionDomain(); } } ); + + // determine if we are running on Android + boolean isAndroid; + try { + isAndroid = loadClass("org.drools.android.DroolsAndroidContext", null) != null && + loadClass("android.os.Build", null) != null && + loadClass("dalvik.system.DexPathList", null) != null; + } catch (Exception e) { + isAndroid = false; + } + IS_ANDROID = isAndroid; } private static Map> classes = Collections.synchronizedMap( new HashMap() ); + private static Map> constructors = Collections.synchronizedMap( new HashMap() ); + private static final String STAR = "*"; public static boolean areNullSafeEquals(Object obj1, Object obj2) { @@ -108,8 +124,8 @@ public static String clazzName(final File base, final File file) { final int rootLength = base.getAbsolutePath().length(); final String absFileName = file.getAbsolutePath(); - final int p = absFileName.lastIndexOf( '.' ); - final String relFileName = absFileName.substring( rootLength + 1, p ); + final int p = absFileName.lastIndexOf('.'); + final String relFileName = absFileName.substring(rootLength + 1, p); return relFileName.replace(File.separatorChar, '.'); } @@ -117,7 +133,7 @@ public static String relative(final File base, final File file) { final int rootLength = base.getAbsolutePath().length(); final String absFileName = file.getAbsolutePath(); - return absFileName.substring( rootLength + 1 ); + return absFileName.substring(rootLength + 1); } public static String canonicalName(Class clazz) { @@ -137,19 +153,14 @@ public static String canonicalName(Class clazz) { return name.toString(); } - public static Object instantiateObject(String className) { - return instantiateObject( className, - null ); - } - /** - * This method will attempt to create an instance of the specified Class. It uses + * This method will attempt to load the specified Class. It uses * a syncrhonized HashMap to cache the reflection Class lookup. * @param className * @return */ - public static Object instantiateObject(String className, - ClassLoader classLoader) { + public static Class loadClass(String className, + ClassLoader classLoader) { Class cls = (Class) classes.get( className ); if ( cls == null ) { try { @@ -197,10 +208,25 @@ public static Object instantiateObject(String className, throw new RuntimeException( "Unable to load class '" + className + "'" ); } } + return cls; + } + public static Object instantiateObject(String className) { + return instantiateObject(className, + (ClassLoader)null); + } + + /** + * This method will attempt to create an instance of the specified Class. It uses + * a syncrhonized HashMap to cache the reflection Class lookup. + * @param className + * @return + */ + public static Object instantiateObject(String className, + ClassLoader classLoader) { Object object; try { - object = cls.newInstance(); + object = loadClass(className, classLoader).newInstance(); } catch ( Throwable e ) { throw new RuntimeException( "Unable to instantiate object for class '" + className + "'", e ); @@ -208,6 +234,44 @@ public static Object instantiateObject(String className, return object; } + /** + * This method will attempt to create an instance of the specified Class. It uses + * a synchronized HashMap to cache the reflection Class lookup. It will execute the default + * constructor with the passed in arguments + * @param className + * @param args arguments to default constructor + * @return + */ + public static Object instantiateObject(String className, + ClassLoader classLoader, Object...args) { + Constructor c = (Constructor) constructors.get( className ); + if ( c == null ) { + c = loadClass(className, classLoader).getConstructors()[0]; + constructors.put(className, c); + } + + Object object; + try { + object = c.newInstance(args); + } catch ( Throwable e ) { + throw new RuntimeException( "Unable to instantiate object for class '" + className + + "' with constructor " + c, e ); + } + return object; + } + + /** + * This method will attempt to create an instance of the specified Class. It uses + * a synchronized HashMap to cache the reflection Class lookup. It will execute the default + * constructor with the passed in arguments + * @param className + * @param args arguments to default constructor + * @return + */ + public static Object instantiateObject(String className, Object...args) { + return instantiateObject(className, null, args); + } + /** * Populates the import style pattern map from give comma delimited string * @param patterns @@ -641,4 +705,12 @@ public static boolean isOSX() { String os = System.getProperty("os.name"); return os.toUpperCase().contains( "MAC OS X" ); } + + /** + * Checks if running on Android operating system + */ + public static boolean isAndroid() { + return IS_ANDROID; + } + } diff --git a/drools-core/src/main/java/org/drools/core/util/Drools.java b/drools-core/src/main/java/org/drools/core/util/Drools.java index 0027ab2173c..78bb442b4cc 100644 --- a/drools-core/src/main/java/org/drools/core/util/Drools.java +++ b/drools-core/src/main/java/org/drools/core/util/Drools.java @@ -18,7 +18,7 @@ public class Drools { static { droolsFullVersion = Drools.class.getPackage().getImplementationVersion(); - if (droolsFullVersion == null) { + if (droolsFullVersion == null || droolsFullVersion.equals("0.0")) { InputStream is = null; try { is = Drools.class.getClassLoader().getResourceAsStream("drools.versions.properties"); diff --git a/drools-core/src/main/java/org/drools/core/util/IoUtils.java b/drools-core/src/main/java/org/drools/core/util/IoUtils.java index 8a0ce362294..12bbe87e5fc 100644 --- a/drools-core/src/main/java/org/drools/core/util/IoUtils.java +++ b/drools-core/src/main/java/org/drools/core/util/IoUtils.java @@ -125,6 +125,9 @@ public static Map indexZipFile(java.io.File jarFile) { Enumeration< ? extends ZipEntry> entries = zipFile.entries(); while ( entries.hasMoreElements() ) { ZipEntry entry = entries.nextElement(); + if (entry.getName().endsWith(".dex")) { + continue; //avoid out of memory error, it is useless anyway + } byte[] bytes = readBytesFromInputStream( zipFile.getInputStream( entry ) ); files.put( entry.getName(), bytes ); diff --git a/drools-core/src/main/java/org/drools/core/util/MemoryUtil.java b/drools-core/src/main/java/org/drools/core/util/MemoryUtil.java index 9e4a930f4a9..ee614ce7e19 100644 --- a/drools-core/src/main/java/org/drools/core/util/MemoryUtil.java +++ b/drools-core/src/main/java/org/drools/core/util/MemoryUtil.java @@ -11,26 +11,38 @@ public class MemoryUtil { private MemoryUtil() { } static { - MemoryPoolMXBean permGenBean = null; - for (MemoryPoolMXBean mx : ManagementFactory.getMemoryPoolMXBeans()) { - if (mx.getName() != null && mx.getName().contains("Perm")) { - permGenBean = mx; - break; + if(!ClassUtils.isAndroid()) { + MemoryPoolMXBean permGenBean = null; + for (MemoryPoolMXBean mx : ManagementFactory.getMemoryPoolMXBeans()) { + if (mx.getName() != null && mx.getName().contains("Perm")) { + permGenBean = mx; + break; + } } + permGenStats = new MemoryStats(permGenBean); + } else { + permGenStats = new MemoryStats(); } - permGenStats = new MemoryStats(permGenBean); } public static class MemoryStats { private final MemoryPoolMXBean memoryBean; + public MemoryStats() { + memoryBean = null; + } + public MemoryStats(MemoryPoolMXBean memoryBean) { this.memoryBean = memoryBean; } public boolean isUsageThresholdExceeded(int threshold) { - MemoryUsage memoryUsage = getMemoryUsage(); - return memoryUsage != null && memoryUsage.getUsed() * 100 / memoryUsage.getMax() >= threshold; + if (!ClassUtils.isAndroid()) { + MemoryUsage memoryUsage = getMemoryUsage(); + return memoryUsage != null && memoryUsage.getUsed() * 100 / memoryUsage.getMax() >= threshold; + } else { + return false; + } } public MemoryUsage getMemoryUsage() { diff --git a/kie-maven-plugin/pom.xml b/kie-maven-plugin/pom.xml index d566d6ff62b..ac54ad75f1f 100644 --- a/kie-maven-plugin/pom.xml +++ b/kie-maven-plugin/pom.xml @@ -22,10 +22,90 @@ kie + + + generated-helpmojo + + helpmojo + + + + generate-descriptor + + descriptor + + + + + + org.codehaus.plexus + plexus-component-metadata + + + + generate-metadata + generate-test-metadata + + + + + + io.takari.maven.plugins + takari-lifecycle-plugin + 1.10.2 + true + + + testProperties + process-test-resources + + testProperties + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + -Xms512m -Xmx1024m -XX:MaxPermSize=1024m + + + + + org.apache.maven.plugin-tools + maven-plugin-annotations + 3.3 + provided + + + org.codehaus.plexus + plexus-component-annotations + 1.5.5 + + + org.codehaus.plexus + plexus-container-default + 1.5.5 + + + io.takari.maven.plugins + takari-plugin-testing + 2.1.0 + + + io.takari.maven.plugins + takari-plugin-integration-testing + 2.1.0 + pom + + + + org.apache.maven @@ -44,6 +124,23 @@ maven-plugin-testing-harness test + + org.apache.maven.plugin-tools + maven-plugin-annotations + provided + + + org.codehaus.plexus + plexus-component-annotations + + + org.codehaus.plexus + plexus-classworlds + + + org.codehaus.plexus + plexus-container-default + com.google.protobuf @@ -63,6 +160,28 @@ org.kie kie-api + + org.kie + kie-internal + + + + io.takari.maven.plugins + takari-plugin-testing + test + + + io.takari.maven.plugins + takari-plugin-integration-testing + pom + test + + + + junit + junit + test + diff --git a/kie-maven-plugin/src/main/java/org/kie/maven/plugin/IncludeProjectDependenciesComponentConfigurator.java b/kie-maven-plugin/src/main/java/org/kie/maven/plugin/IncludeProjectDependenciesComponentConfigurator.java new file mode 100644 index 00000000000..a86ba4eb18f --- /dev/null +++ b/kie-maven-plugin/src/main/java/org/kie/maven/plugin/IncludeProjectDependenciesComponentConfigurator.java @@ -0,0 +1,97 @@ +/* + * Copyright 2015 JBoss Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.kie.maven.plugin; + +import org.codehaus.classworlds.ClassRealm; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.component.configurator.AbstractComponentConfigurator; +import org.codehaus.plexus.component.configurator.ComponentConfigurationException; +import org.codehaus.plexus.component.configurator.ComponentConfigurator; +import org.codehaus.plexus.component.configurator.ConfigurationListener; +import org.codehaus.plexus.component.configurator.converters.composite.ObjectWithFieldsConverter; +import org.codehaus.plexus.component.configurator.converters.special.ClassRealmConverter; +import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException; +import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; +import org.codehaus.plexus.configuration.PlexusConfiguration; +import org.codehaus.plexus.logging.Logger; +import org.codehaus.plexus.logging.console.ConsoleLogger; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +/** + * A custom ComponentConfigurator which adds the project's runtime classpath elements + * to the + */ +@Component(role=ComponentConfigurator.class, hint="include-project-dependencies") +public class IncludeProjectDependenciesComponentConfigurator extends AbstractComponentConfigurator { + + private static final Logger LOGGER = new ConsoleLogger(Logger.LEVEL_DEBUG, "Configurator"); + + public void configureComponent( Object component, PlexusConfiguration configuration, + ExpressionEvaluator expressionEvaluator, ClassRealm containerRealm, + ConfigurationListener listener ) + throws ComponentConfigurationException { + + addProjectDependenciesToClassRealm(expressionEvaluator, containerRealm); + + converterLookup.registerConverter( new ClassRealmConverter( containerRealm ) ); + + ObjectWithFieldsConverter converter = new ObjectWithFieldsConverter(); + + converter.processConfiguration( converterLookup, component, containerRealm.getClassLoader(), configuration, + expressionEvaluator, listener ); + } + + private void addProjectDependenciesToClassRealm(ExpressionEvaluator expressionEvaluator, ClassRealm containerRealm) throws ComponentConfigurationException { + List runtimeClasspathElements; + try { + //noinspection unchecked + runtimeClasspathElements = (List) expressionEvaluator.evaluate("${project.runtimeClasspathElements}"); + } catch (ExpressionEvaluationException e) { + throw new ComponentConfigurationException("There was a problem evaluating: ${project.runtimeClasspathElements}", e); + } + + // Add the project dependencies to the ClassRealm + final URL[] urls = buildURLs(runtimeClasspathElements); + for (URL url : urls) { + containerRealm.addConstituent(url); + } + } + + private URL[] buildURLs(List runtimeClasspathElements) throws ComponentConfigurationException { + // Add the projects classes and dependencies + List urls = new ArrayList(runtimeClasspathElements.size()); + for (String element : runtimeClasspathElements) { + try { + final URL url = new File(element).toURI().toURL(); + urls.add(url); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Added to project class loader: " + url); + } + } catch (MalformedURLException e) { + throw new ComponentConfigurationException("Unable to access project dependency: " + element, e); + } + } + + // Add the plugin's dependencies (so Trove stuff works if Trove isn't on + return urls.toArray(new URL[urls.size()]); + } + +} diff --git a/kie-maven-plugin/src/main/java/org/kie/maven/plugin/SerializeMojo.java b/kie-maven-plugin/src/main/java/org/kie/maven/plugin/SerializeMojo.java new file mode 100644 index 00000000000..0432f552260 --- /dev/null +++ b/kie-maven-plugin/src/main/java/org/kie/maven/plugin/SerializeMojo.java @@ -0,0 +1,93 @@ +/* + * Copyright 2015 JBoss Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.kie.maven.plugin; + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.drools.core.util.DroolsStreamUtils; +import org.kie.api.KieBase; +import org.kie.api.KieServices; +import org.kie.api.builder.Message; +import org.kie.api.builder.Results; +import org.kie.api.runtime.KieContainer; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.List; + +/** + * Compiles and serializes knowledge packages. + */ +@Mojo(name = "serialize", + requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, + requiresProject = true, + defaultPhase = LifecyclePhase.COMPILE, + configurator = "include-project-dependencies") +public class SerializeMojo extends AbstractMojo { + + /** + * KnowledgeBases to serialize + */ + @Parameter(property = "kie.kiebases",required = true) + private List kiebases; + + /** + * Output folder + */ + @Parameter(property = "kie.resDirectory", defaultValue = "${project.basedir}/src/main/res/raw" ) + private String resDirectory; + + + @Override + public void execute() throws MojoExecutionException, MojoFailureException { + try { + File outputFolder = new File(resDirectory); + outputFolder.mkdirs(); + + KieServices ks = KieServices.Factory.get(); + KieContainer kc = ks.newKieClasspathContainer(); + Results messages = kc.verify(); + + List warnings = messages.getMessages(Message.Level.WARNING); + for (Message warning : warnings) { + getLog().warn(warnings.toString()); + } + List errors = messages.getMessages(Message.Level.ERROR); + if (!errors.isEmpty()) { + for (Message error : errors) { + getLog().error(error.toString()); + } + throw new MojoFailureException("Build failed!"); + } + + for(String kbase : kiebases) { + KieBase kb = kc.getKieBase(kbase); + getLog().info("Writing KBase: " + kbase); + File file = new File(outputFolder, kbase.replace('.', '_').toLowerCase()); + FileOutputStream out = new FileOutputStream(file); + DroolsStreamUtils.streamOut(out, kb.getKiePackages()); + out.close(); + } + } catch (Exception e) { + throw new MojoExecutionException("error", e); + } + } +} diff --git a/kie-maven-plugin/src/main/java/org/kie/maven/plugin/TouchResourcesMojo.java b/kie-maven-plugin/src/main/java/org/kie/maven/plugin/TouchResourcesMojo.java new file mode 100644 index 00000000000..7986925e170 --- /dev/null +++ b/kie-maven-plugin/src/main/java/org/kie/maven/plugin/TouchResourcesMojo.java @@ -0,0 +1,92 @@ +/* + * Copyright 2015 JBoss Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.kie.maven.plugin; + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.project.MavenProject; +import org.drools.core.util.DroolsStreamUtils; +import org.kie.api.KieBase; +import org.kie.api.KieServices; +import org.kie.api.builder.Message; +import org.kie.api.builder.Results; +import org.kie.api.io.ResourceType; +import org.kie.api.runtime.KieContainer; +import org.kie.internal.builder.KnowledgeBuilder; +import org.kie.internal.builder.KnowledgeBuilderConfiguration; +import org.kie.internal.builder.KnowledgeBuilderError; +import org.kie.internal.builder.KnowledgeBuilderFactory; +import org.kie.internal.definition.KnowledgePackage; +import org.kie.internal.io.ResourceFactory; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.Collection; +import java.util.List; +import java.util.Properties; + +/** + * Compiles and serializes knowledge packages. + * @author kedzie + * + */ +@Mojo(name = "touch", + requiresProject = true, + defaultPhase = LifecyclePhase.GENERATE_RESOURCES) +public class TouchResourcesMojo extends AbstractMojo { + + /** + * DRL rule package + */ + @Parameter(property = "kie.ruleFiles",required = true) + private List ruleFiles; + + /** + * KnowledgeBases to serialize + */ + @Parameter(property = "kie.kiebases",required = true) + private List kiebases; + + /** + * Output folder + */ + @Parameter(property = "kie.resDirectory", defaultValue = "${project.basedir}/res/raw" ) + private String resDirectory; + + @Parameter(defaultValue = "${project}", required = true, readonly = true) + private MavenProject project; + + @Override + public void execute() throws MojoExecutionException, MojoFailureException { + try { + File outputFolder = new File(resDirectory); + outputFolder.mkdirs(); + + for(String kbase : kiebases) { + getLog().info("Touching KBase: " + kbase); + File file = new File(outputFolder, kbase.replace('.', '_').toLowerCase()); + file.createNewFile(); + } + } catch (Exception e) { + throw new MojoExecutionException("error", e); + } + } +} diff --git a/kie-maven-plugin/src/test/java/org/kie/maven/plugin/BuildMojoIntegrationTest.java b/kie-maven-plugin/src/test/java/org/kie/maven/plugin/BuildMojoIntegrationTest.java new file mode 100644 index 00000000000..f2500c7adf6 --- /dev/null +++ b/kie-maven-plugin/src/test/java/org/kie/maven/plugin/BuildMojoIntegrationTest.java @@ -0,0 +1,56 @@ +/* + * Copyright 2015 JBoss Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.kie.maven.plugin; + +import io.takari.maven.testing.TestResources; +import io.takari.maven.testing.executor.MavenExecutionResult; +import io.takari.maven.testing.executor.MavenRuntime; +import io.takari.maven.testing.executor.MavenVersions; +import io.takari.maven.testing.executor.junit.MavenJUnitTestRunner; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.File; + +/** + * Integration test for kjar + */ +@RunWith(MavenJUnitTestRunner.class) +@MavenVersions({"3.2.3"}) +public class BuildMojoIntegrationTest { + + @Rule + public final TestResources resources = new TestResources(); + + public final MavenRuntime mavenRuntime; + + public BuildMojoIntegrationTest(MavenRuntime.MavenRuntimeBuilder builder) throws Exception { + this.mavenRuntime = builder.withCliOptions( "-X" ).build(); + } + + @Test + public void buildDeployAndRun() throws Exception { + File basedir = resources.getBasedir("kjar-1"); + MavenExecutionResult result = mavenRuntime + .forProject(basedir) + .execute("clean", + "install"); + + result.assertErrorFreeLog(); + } +} + diff --git a/kie-maven-plugin/src/test/projects/kjar-1/pom.xml b/kie-maven-plugin/src/test/projects/kjar-1/pom.xml new file mode 100644 index 00000000000..40918344ed8 --- /dev/null +++ b/kie-maven-plugin/src/test/projects/kjar-1/pom.xml @@ -0,0 +1,53 @@ + + + + 4.0.0 + + org.drools + drools-multiproject + 6.3.0-SNAPSHOT + + + org.kie + kie-maven-plugin-example + + kjar + + + + org.drools + drools-core + + + org.drools + drools-compiler + + + + + + + org.kie + kie-maven-plugin + ${it-plugin.version} + true + + + serialize + + serialize + + compile + + + KBase1 + + ${project.build.outputDirectory} + + + + + + + diff --git a/kie-maven-plugin/src/test/projects/kjar-1/src/main/java/org/kie/sample/model/Fire.java b/kie-maven-plugin/src/test/projects/kjar-1/src/main/java/org/kie/sample/model/Fire.java new file mode 100644 index 00000000000..d01f76a2662 --- /dev/null +++ b/kie-maven-plugin/src/test/projects/kjar-1/src/main/java/org/kie/sample/model/Fire.java @@ -0,0 +1,35 @@ +/* + * Copyright 2015 JBoss Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.kie.sample.model; + +public class Fire { + + private Room room; + + public Fire() { } + + public Fire(Room room) { + this.room = room; + } + + public Room getRoom() { + return room; + } + + public void setRoom(Room room) { + this.room = room; + } +} diff --git a/kie-maven-plugin/src/test/projects/kjar-1/src/main/java/org/kie/sample/model/Room.java b/kie-maven-plugin/src/test/projects/kjar-1/src/main/java/org/kie/sample/model/Room.java new file mode 100644 index 00000000000..76bfb013b22 --- /dev/null +++ b/kie-maven-plugin/src/test/projects/kjar-1/src/main/java/org/kie/sample/model/Room.java @@ -0,0 +1,51 @@ +/* + * Copyright 2015 JBoss Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.kie.sample.model; + +public class Room { + + private String name; + + public Room() { } + + public Room(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Room)) { return false; } + return name.equals(((Room) obj).getName()); + } + + @Override + public String toString() { + return name; + } +} diff --git a/kie-maven-plugin/src/test/projects/kjar-1/src/main/java/org/kie/sample/model/Sprinkler.java b/kie-maven-plugin/src/test/projects/kjar-1/src/main/java/org/kie/sample/model/Sprinkler.java new file mode 100644 index 00000000000..b783e9dec73 --- /dev/null +++ b/kie-maven-plugin/src/test/projects/kjar-1/src/main/java/org/kie/sample/model/Sprinkler.java @@ -0,0 +1,60 @@ +/* + * Copyright 2015 JBoss Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.kie.sample.model; + +public class Sprinkler { + + private Room room; + private boolean on = false; + + public Sprinkler() { } + + public Sprinkler(Room room) { + this.room = room; + } + + public Room getRoom() { + return room; + } + + public void setRoom(Room room) { + this.room = room; + } + + public boolean isOn() { + return on; + } + + public void setOn(boolean on) { + this.on = on; + } + + @Override + public int hashCode() { + return room.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Sprinkler)) { return false; } + return room.equals(((Sprinkler) obj).getRoom()); + } + + @Override + public String toString() { + return "Sprinkler for " + room; + } +} diff --git a/kie-maven-plugin/src/test/projects/kjar-1/src/main/resources/FireAlarmKBase/alarm.drl b/kie-maven-plugin/src/test/projects/kjar-1/src/main/resources/FireAlarmKBase/alarm.drl new file mode 100644 index 00000000000..e0583e6274b --- /dev/null +++ b/kie-maven-plugin/src/test/projects/kjar-1/src/main/resources/FireAlarmKBase/alarm.drl @@ -0,0 +1,3 @@ +package org.kie.sample.model +declare Alarm +end \ No newline at end of file diff --git a/kie-maven-plugin/src/test/projects/kjar-1/src/main/resources/FireAlarmKBase/rules.drl b/kie-maven-plugin/src/test/projects/kjar-1/src/main/resources/FireAlarmKBase/rules.drl new file mode 100644 index 00000000000..64b22f063f0 --- /dev/null +++ b/kie-maven-plugin/src/test/projects/kjar-1/src/main/resources/FireAlarmKBase/rules.drl @@ -0,0 +1,23 @@ +package org.kie.sample + +import java.util.* +import org.kie.sample.model.* + +rule "When there is a fire turn on the sprinkler" +when + $fire: Fire($room : room) + $sprinkler : Sprinkler( room == $room, !on ) +then + modify( $sprinkler ) { setOn( true ) }; + System.out.println( "Turn on the sprinkler for room " + $room.getName() ); +end + +rule "When the fire is gone turn off the sprinkler" +when + $room : Room( ) + $sprinkler : Sprinkler( room == $room, on ) + not Fire( room == $room ) +then + modify( $sprinkler ) { setOn( false ) }; + System.out.println( "Turn off the sprinkler for room " + $room.getName() ); +end diff --git a/kie-maven-plugin/src/test/projects/kjar-1/src/main/resources/FireAlarmKBase/rules2.drl b/kie-maven-plugin/src/test/projects/kjar-1/src/main/resources/FireAlarmKBase/rules2.drl new file mode 100644 index 00000000000..45a82a16705 --- /dev/null +++ b/kie-maven-plugin/src/test/projects/kjar-1/src/main/resources/FireAlarmKBase/rules2.drl @@ -0,0 +1,29 @@ +package org.kie.sample + +import java.util.* +import org.kie.sample.model.* + +rule "Raise the alarm when we have one or more fires" +when + exists Fire() +then + insert( new Alarm() ); + System.out.println( "Raise the alarm" ); +end + +rule "Cancel the alarm when all the fires have gone" +when + not Fire() + $alarm : Alarm() +then + retract( $alarm ); + System.out.println( "Cancel the alarm" ); +end + +rule "Status output when things are ok" +when + not Alarm() + not Sprinkler( on == true ) +then + System.out.println( "Everything is ok" ); +end diff --git a/kie-maven-plugin/src/test/projects/kjar-1/src/main/resources/KBase1/decA.drl b/kie-maven-plugin/src/test/projects/kjar-1/src/main/resources/KBase1/decA.drl new file mode 100644 index 00000000000..c1b82af7bab --- /dev/null +++ b/kie-maven-plugin/src/test/projects/kjar-1/src/main/resources/KBase1/decA.drl @@ -0,0 +1,4 @@ +package org.kie.test +declare FactA + fieldB: FactB +end \ No newline at end of file diff --git a/kie-maven-plugin/src/test/projects/kjar-1/src/main/resources/KBase1/decB.drl b/kie-maven-plugin/src/test/projects/kjar-1/src/main/resources/KBase1/decB.drl new file mode 100644 index 00000000000..867cc668904 --- /dev/null +++ b/kie-maven-plugin/src/test/projects/kjar-1/src/main/resources/KBase1/decB.drl @@ -0,0 +1,4 @@ +package org.kie.test +declare FactB + fieldA: FactA +end \ No newline at end of file diff --git a/kie-maven-plugin/src/test/projects/kjar-1/src/main/resources/KBase1/rule.drl b/kie-maven-plugin/src/test/projects/kjar-1/src/main/resources/KBase1/rule.drl new file mode 100644 index 00000000000..45e0360a9ca --- /dev/null +++ b/kie-maven-plugin/src/test/projects/kjar-1/src/main/resources/KBase1/rule.drl @@ -0,0 +1,6 @@ +package org.kie.test +rule R1 when + $fieldA : FactA( $fieldB : fieldB ) + FactB( this == $fieldB, fieldA == $fieldA ) +then +end \ No newline at end of file diff --git a/kie-maven-plugin/src/test/projects/kjar-1/src/main/resources/META-INF/kmodule.xml b/kie-maven-plugin/src/test/projects/kjar-1/src/main/resources/META-INF/kmodule.xml new file mode 100644 index 00000000000..2688cea1c20 --- /dev/null +++ b/kie-maven-plugin/src/test/projects/kjar-1/src/main/resources/META-INF/kmodule.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/kie-maven-plugin/src/test/projects/kjar-1/src/test/java/org/kie/kproject/KProjectTest.java b/kie-maven-plugin/src/test/projects/kjar-1/src/test/java/org/kie/kproject/KProjectTest.java new file mode 100644 index 00000000000..770f55ea266 --- /dev/null +++ b/kie-maven-plugin/src/test/projects/kjar-1/src/test/java/org/kie/kproject/KProjectTest.java @@ -0,0 +1,52 @@ +/* + * Copyright 2015 JBoss Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.kie.kproject; + +import org.junit.Ignore; +import org.junit.Test; +import org.kie.api.KieServices; +import org.kie.api.runtime.KieContainer; +import org.kie.api.runtime.KieSession; +import org.kie.api.runtime.rule.FactHandle; +import org.kie.sample.model.Fire; +import org.kie.sample.model.Room; +import org.kie.sample.model.Sprinkler; + +import static org.junit.Assert.assertEquals; + +public class KProjectTest { + + @Test + public void testKJar() throws Exception { + KieServices ks = KieServices.Factory.get(); + KieContainer kContainer = ks.getKieClasspathContainer(); + KieSession kSession = kContainer.newKieSession("FireAlarmKBase.session"); + + Room room = new Room("101"); + kSession.insert(room); + Sprinkler sprinkler = new Sprinkler(room); + kSession.insert(sprinkler); + Fire fire = new Fire(room); + FactHandle fireFH = kSession.insert(fire); + + int rules = kSession.fireAllRules(); + assertEquals(2, rules); + + kSession.delete(fireFH); + rules = kSession.fireAllRules(); + assertEquals(3, rules); + } +}