[jboss-svn-commits] JBL Code SVN: r20155 - in labs/jbossrules/trunk: drools-compiler/src/test/java/org/drools/integrationtests and 6 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Sat May 24 14:01:51 EDT 2008
Author: tirelli
Date: 2008-05-24 14:01:50 -0400 (Sat, 24 May 2008)
New Revision: 20155
Modified:
labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/PackageBuilder.java
labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/MiscTest.java
labs/jbossrules/trunk/drools-compiler/src/test/resources/org/drools/integrationtests/test_GeneratedBeans.drl
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/ClassFieldAccessorFactory.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractRuleBase.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/ClassDefinition.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/FieldDefinition.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/FactField.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/FactType.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/JavaDialectData.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/MapBackedClassLoader.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/Package.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/asm/ClassFieldInspector.java
Log:
Fixing type resolution in rule consequences for generated beans
Modified: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/PackageBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/PackageBuilder.java 2008-05-24 13:51:11 UTC (rev 20154)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/PackageBuilder.java 2008-05-24 18:01:50 UTC (rev 20155)
@@ -55,10 +55,7 @@
import org.drools.lang.descr.TypeDeclarationDescr;
import org.drools.lang.descr.TypeFieldDescr;
import org.drools.process.core.Process;
-import org.drools.rule.CompositePackageClassLoader;
import org.drools.rule.ImportDeclaration;
-import org.drools.rule.JavaDialectData;
-import org.drools.rule.MapBackedClassLoader;
import org.drools.rule.Package;
import org.drools.rule.Rule;
import org.drools.rule.TypeDeclaration;
@@ -98,8 +95,6 @@
private DialectRegistry dialectRegistry;
- private MapBackedClassLoader generatedBeanClassLoader;
-
/**
* Use this when package is starting from scratch.
*/
@@ -555,12 +550,7 @@
}
byte[] d = cb.buildClass(def);
- if (this.generatedBeanClassLoader == null) {
- CompositePackageClassLoader ccl = (CompositePackageClassLoader) this.pkg.getDialectDatas().getClassLoader();
- this.generatedBeanClassLoader = new MapBackedClassLoader(this.configuration.getClassLoader());
- ccl.addClassLoader(this.generatedBeanClassLoader);
- }
- this.generatedBeanClassLoader.addClass( fullName, d);
+ this.pkg.getPackageScopeClassLoader().addClass( fullName, d);
type.setTypeClassDef( def );
} catch (Exception e) {
e.printStackTrace();
Modified: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/MiscTest.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/MiscTest.java 2008-05-24 13:51:11 UTC (rev 20154)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/MiscTest.java 2008-05-24 18:01:50 UTC (rev 20155)
@@ -16,6 +16,7 @@
* limitations under the License.
*/
+import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInput;
@@ -24,6 +25,8 @@
import java.io.StringReader;
import java.math.BigDecimal;
import java.math.BigInteger;
+import java.net.URL;
+import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
@@ -518,7 +521,9 @@
}
public void testGeneratedBeans1() throws Exception {
- final PackageBuilder builder = new PackageBuilder();
+ final PackageBuilderConfiguration pbconf = new PackageBuilderConfiguration();
+ pbconf.setDumpDir( new File("target") );
+ final PackageBuilder builder = new PackageBuilder(pbconf);
builder.addPackageFromDrl( new InputStreamReader( getClass().getResourceAsStream( "test_GeneratedBeans.drl" ) ) );
assertFalse( builder.getErrors().toString(),
builder.hasErrors() );
@@ -534,6 +539,9 @@
RuleBase ruleBase = RuleBaseFactory.newRuleBase( conf );
ruleBase.addPackage( p );
+ // test rulebase serialization
+ ruleBase = SerializationHelper.serializeObject(ruleBase);
+
// Retrieve the generated fact type
FactType cheeseFact = ruleBase.getFactType( "org.drools.generatedbeans.Cheese" );
@@ -599,7 +607,7 @@
// checking results
assertEquals( 2,
result.size() );
- assertEquals( "OK",
+ assertEquals( person,
result.get( 1 ) );
}
@@ -5305,5 +5313,32 @@
list.size() );
}
+
+ public class SubvertedClassLoader extends URLClassLoader {
+ private static final long serialVersionUID = 400L;
+
+ public SubvertedClassLoader(final URL[] urls,
+ final ClassLoader parentClassLoader) {
+ super( urls,
+ parentClassLoader );
+ }
+
+ protected synchronized Class loadClass(String name,
+ boolean resolve) throws ClassNotFoundException {
+ // First, check if the class has already been loaded
+ Class c = findLoadedClass( name );
+ if ( c == null ) {
+ try {
+ c = findClass( name );
+ } catch ( ClassNotFoundException e ) {
+ c = super.loadClass( name,
+ resolve );
+ }
+ }
+ return c;
+ }
+ }
+
+
}
Modified: labs/jbossrules/trunk/drools-compiler/src/test/resources/org/drools/integrationtests/test_GeneratedBeans.drl
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/resources/org/drools/integrationtests/test_GeneratedBeans.drl 2008-05-24 13:51:11 UTC (rev 20154)
+++ labs/jbossrules/trunk/drools-compiler/src/test/resources/org/drools/integrationtests/test_GeneratedBeans.drl 2008-05-24 18:01:50 UTC (rev 20155)
@@ -23,5 +23,5 @@
$cheese : Cheese( type == "stilton" )
$person : Person( age== 7, likes == $cheese )
then
- list.add( "OK" );
+ list.add( $person );
end
\ No newline at end of file
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/ClassFieldAccessorFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/ClassFieldAccessorFactory.java 2008-05-24 13:51:11 UTC (rev 20154)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/ClassFieldAccessorFactory.java 2008-05-24 18:01:50 UTC (rev 20155)
@@ -139,6 +139,7 @@
} catch ( final RuntimeDroolsException e ) {
throw e;
} catch ( final Exception e ) {
+ e.printStackTrace();
throw new RuntimeDroolsException( e );
}
}
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractRuleBase.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractRuleBase.java 2008-05-24 13:51:11 UTC (rev 20154)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractRuleBase.java 2008-05-24 18:01:50 UTC (rev 20155)
@@ -457,11 +457,12 @@
if ( pkg == null ) {
pkg = new Package( newPkg.getName(),
- newPkg.getDialectDatas().getParentClassLoader() );
+ newPkg.getPackageScopeClassLoader() );
pkgs.put( pkg.getName(),
pkg );
this.packageClassLoader.addClassLoader( pkg.getDialectDatas().getClassLoader() );
} else {
+ pkg.getPackageScopeClassLoader().getStore().putAll( newPkg.getPackageScopeClassLoader().getStore() );
this.packageClassLoader.addClassLoader( newPkg.getDialectDatas().getClassLoader() );
}
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/ClassDefinition.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/ClassDefinition.java 2008-05-24 13:51:11 UTC (rev 20154)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/ClassDefinition.java 2008-05-24 18:01:50 UTC (rev 20155)
@@ -18,6 +18,8 @@
import java.beans.IntrospectionException;
import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
@@ -38,7 +40,10 @@
*
* @author etirelli
*/
-public class ClassDefinition implements FactType {
+public class ClassDefinition
+ implements
+ FactType {
+
private String className;
private String superClass;
private String[] interfaces;
@@ -46,6 +51,12 @@
private Map<String, FieldDefinition> fields = new LinkedHashMap<String, FieldDefinition>();
+ public ClassDefinition() {
+ this( null,
+ null,
+ null );
+ }
+
public ClassDefinition(String className) {
this( className,
null,
@@ -74,6 +85,23 @@
this.setInterfaces( interfaces );
}
+ public void readExternal(ObjectInput in) throws IOException,
+ ClassNotFoundException {
+ this.className = (String) in.readObject();
+ this.superClass = (String) in.readObject();
+ this.interfaces = (String[]) in.readObject();
+ this.definedClass = (Class<?>) in.readObject();
+ this.fields = (Map<String, FieldDefinition>) in.readObject();
+ }
+
+ public void writeExternal(ObjectOutput out) throws IOException {
+ out.writeObject( this.className );
+ out.writeObject( this.superClass );
+ out.writeObject( this.interfaces );
+ out.writeObject( this.definedClass );
+ out.writeObject( this.fields );
+ }
+
/**
* @return Returns the name.
*/
@@ -98,7 +126,7 @@
/**
* @param className The class to set.
*/
- public void setDefinedClass(final Class< ? > definedClass) {
+ public void setDefinedClass(final Class< ? > definedClass) {
this.definedClass = definedClass;
}
@@ -156,9 +184,14 @@
ClassFieldAccessorCache cache = ClassFieldAccessorCache.getInstance();
for ( FieldDefinition attrDef : this.fields.values() ) {
- ClassFieldReader reader = cache.getReader( this.getDefinedClass(), attrDef.getName(), this.getClass().getClassLoader() );
- ClassFieldWriter writer = cache.getWriter( this.getDefinedClass(), attrDef.getName(), this.getClass().getClassLoader() );
- ClassFieldAccessor accessor = new ClassFieldAccessor( reader, writer );
+ ClassFieldReader reader = cache.getReader( this.getDefinedClass(),
+ attrDef.getName(),
+ this.getClass().getClassLoader() );
+ ClassFieldWriter writer = cache.getWriter( this.getDefinedClass(),
+ attrDef.getName(),
+ this.getClass().getClassLoader() );
+ ClassFieldAccessor accessor = new ClassFieldAccessor( reader,
+ writer );
attrDef.setFieldAccessor( accessor );
}
}
@@ -195,7 +228,8 @@
return getClassName();
}
- public Object newInstance() throws InstantiationException, IllegalAccessException {
+ public Object newInstance() throws InstantiationException,
+ IllegalAccessException {
return this.definedClass.newInstance();
}
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/FieldDefinition.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/FieldDefinition.java 2008-05-24 13:51:11 UTC (rev 20154)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/factmodel/FieldDefinition.java 2008-05-24 18:01:50 UTC (rev 20155)
@@ -16,6 +16,9 @@
* limitations under the License.
*/
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
import java.lang.reflect.InvocationTargetException;
import org.drools.base.ClassFieldAccessor;
@@ -26,13 +29,18 @@
*
* @author etirelli
*/
-public class FieldDefinition implements FactField {
- private String name = null;
- private String type = null;
- private boolean key = false;
+public class FieldDefinition
+ implements
+ FactField {
+ private String name = null;
+ private String type = null;
+ private boolean key = false;
- private ClassFieldAccessor accessor = null;
+ private ClassFieldAccessor accessor = null;
+ public FieldDefinition() {
+ }
+
/**
* Default constructor
*
@@ -60,6 +68,21 @@
this.key = key;
}
+ public void readExternal(ObjectInput in) throws IOException,
+ ClassNotFoundException {
+ this.name = (String) in.readObject();
+ this.type = (String) in.readObject();
+ this.key = in.readBoolean();
+ this.accessor = (ClassFieldAccessor) in.readObject();
+ }
+
+ public void writeExternal(ObjectOutput out) throws IOException {
+ out.writeObject( this.name );
+ out.writeObject( this.type );
+ out.writeBoolean( this.key );
+ out.writeObject( this.accessor );
+ }
+
/**
* @return Returns the name.
*/
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/FactField.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/FactField.java 2008-05-24 13:51:11 UTC (rev 20154)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/FactField.java 2008-05-24 18:01:50 UTC (rev 20155)
@@ -25,14 +25,16 @@
*
* @author etirelli
*/
-public interface FactField {
-
- public Class<?> getType();
-
+public interface FactField
+ extends
+ java.io.Externalizable {
+
+ public Class< ? > getType();
+
public String getName();
-
+
public boolean isKey();
public FieldAccessor getFieldAccessor();
-
+
}
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/FactType.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/FactType.java 2008-05-24 13:51:11 UTC (rev 20154)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/FactType.java 2008-05-24 18:01:50 UTC (rev 20155)
@@ -25,15 +25,18 @@
*
* @author etirelli
*/
-public interface FactType {
-
+public interface FactType
+ extends
+ java.io.Externalizable {
+
public String getName();
-
+
public List<FactField> getFields();
-
- public FactField getField( String name );
-
- public Class<?> getFactClass();
- public Object newInstance() throws InstantiationException, IllegalAccessException;
+ public FactField getField(String name);
+
+ public Class< ? > getFactClass();
+
+ public Object newInstance() throws InstantiationException,
+ IllegalAccessException;
}
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/JavaDialectData.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/JavaDialectData.java 2008-05-24 13:51:11 UTC (rev 20154)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/JavaDialectData.java 2008-05-24 18:01:50 UTC (rev 20155)
@@ -320,7 +320,7 @@
final Object invoker) throws ClassNotFoundException,
InstantiationException,
IllegalAccessException {
- final Class clazz = this.classLoader.findClass( className );
+ final Class clazz = ((CompositePackageClassLoader)this.datas.getClassLoader()).findClass( className );
if (clazz != null) {
if ( invoker instanceof ReturnValueRestriction ) {
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/MapBackedClassLoader.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/MapBackedClassLoader.java 2008-05-24 13:51:11 UTC (rev 20154)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/MapBackedClassLoader.java 2008-05-24 18:01:50 UTC (rev 20155)
@@ -111,7 +111,7 @@
public InputStream getResourceAsStream(final String name) {
byte[] bytes = null;
synchronized ( this.store ) {
- bytes = this.store.get( name );
+ bytes = this.store.get( convertResourcePathToClassName( name ) );
}
if ( bytes != null ) {
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/Package.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/Package.java 2008-05-24 13:51:11 UTC (rev 20154)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/rule/Package.java 2008-05-24 18:01:50 UTC (rev 20155)
@@ -36,11 +36,11 @@
/**
* Collection of related <code>Rule</code>s.
- *
+ *
* @see Rule
- *
+ *
* @author <a href="mail:bob at werken.com">bob mcwhirter </a>
- *
+ *
* @version $Id: Package.java,v 1.1 2005/07/26 01:06:31 mproctor Exp $
*/
public class Package
@@ -51,7 +51,7 @@
// ------------------------------------------------------------
/**
- *
+ *
*/
private static final long serialVersionUID = 400L;
@@ -77,24 +77,35 @@
private Map ruleFlows;
- // private JavaDialectData packageCompilationData;
+ // private JavaDialectData packageCompilationData;
private DialectDatas dialectDatas;
-
+
private Map<String, TypeDeclaration> typeDeclarations;
- /** This is to indicate the the package has no errors during the compilation/building phase */
+ /**
+ * This is to indicate the the package has no errors during the
+ * compilation/building phase
+ */
private boolean valid = true;
- /** This will keep a summary error message as to why this package is not valid */
+ /**
+ * This will keep a summary error message as to why this package is not
+ * valid
+ */
private String errorSummary;
-
+
+ /**
+ * A class loader for package scoped artifacts
+ */
+ private transient MapBackedClassLoader packageScopeClassLoader;
+
// ------------------------------------------------------------
// Constructors
// ------------------------------------------------------------
/**
- * Default constructor - for Externalizable. This should never be used by a user, as it
- * will result in an invalid state for the instance.
+ * Default constructor - for Externalizable. This should never be used by a
+ * user, as it will result in an invalid state for the instance.
*/
public Package() {
@@ -102,7 +113,7 @@
/**
* Construct.
- *
+ *
* @param name
* The name of this <code>Package</code>.
*/
@@ -113,7 +124,7 @@
/**
* Construct.
- *
+ *
* @param name
* The name of this <code>Package</code>.
*/
@@ -129,35 +140,78 @@
this.factTemplates = Collections.EMPTY_MAP;
this.functions = Collections.EMPTY_MAP;
- // This classloader test should only be here for unit testing, too much legacy api to want to change by hand at the moment
+ // This classloader test should only be here for unit testing, too much
+ // legacy api to want to change by hand at the moment
if ( parentClassLoader == null ) {
parentClassLoader = Thread.currentThread().getContextClassLoader();
if ( parentClassLoader == null ) {
parentClassLoader = getClass().getClassLoader();
}
}
- //this.packageCompilationData = new JavaDialectData( parentClassLoader );
- this.dialectDatas = new DialectDatas( parentClassLoader );
+ this.packageScopeClassLoader = new MapBackedClassLoader( parentClassLoader );
+ this.dialectDatas = new DialectDatas( this.packageScopeClassLoader );
}
+
+ /**
+ * Construct.
+ *
+ * @param name
+ * The name of this <code>Package</code>.
+ */
+ public Package(final String name,
+ final MapBackedClassLoader packageClassLoader ) {
+ this.name = name;
+ this.imports = new HashMap<String, ImportDeclaration>();
+ this.typeDeclarations = new HashMap<String, TypeDeclaration>();
+ this.staticImports = Collections.EMPTY_SET;
+ this.rules = new LinkedHashMap();
+ this.ruleFlows = Collections.EMPTY_MAP;
+ this.globals = Collections.EMPTY_MAP;
+ this.factTemplates = Collections.EMPTY_MAP;
+ this.functions = Collections.EMPTY_MAP;
+ if( packageClassLoader == null ) {
+ ClassLoader parentClassLoader = null;
+ // This classloader test should only be here for unit testing, too much
+ // legacy api to want to change by hand at the moment
+ if ( parentClassLoader == null ) {
+ parentClassLoader = Thread.currentThread().getContextClassLoader();
+ if ( parentClassLoader == null ) {
+ parentClassLoader = getClass().getClassLoader();
+ }
+ }
+ this.packageScopeClassLoader = new MapBackedClassLoader( parentClassLoader );
+ } else {
+ this.packageScopeClassLoader = packageClassLoader;
+ }
+ this.dialectDatas = new DialectDatas( this.packageScopeClassLoader );
+ }
+
+
/**
- * Handles the write serialization of the Package. Patterns in Rules may reference generated data which cannot be serialized by default methods.
- * The Package uses PackageCompilationData to hold a reference to the generated bytecode. The generated bytecode must be restored before any Rules.
- * @param stream out the stream to write the object to; should be an instance of DroolsObjectOutputStream or OutputStream
- *
+ * Handles the write serialization of the Package. Patterns in Rules may
+ * reference generated data which cannot be serialized by default methods.
+ * The Package uses PackageCompilationData to hold a reference to the
+ * generated bytecode. The generated bytecode must be restored before any
+ * Rules.
+ *
+ * @param stream
+ * out the stream to write the object to; should be an instance
+ * of DroolsObjectOutputStream or OutputStream
+ *
*/
public void writeExternal(ObjectOutput stream) throws IOException {
- boolean isDroolsStream = stream instanceof DroolsObjectOutputStream;
- ByteArrayOutputStream bytes = null;
- ObjectOutput out;
+ boolean isDroolsStream = stream instanceof DroolsObjectOutputStream;
+ ByteArrayOutputStream bytes = null;
+ ObjectOutput out;
- if (isDroolsStream) {
+ if ( isDroolsStream ) {
out = stream;
- }
- else {
+ } else {
bytes = new ByteArrayOutputStream();
- out = new DroolsObjectOutputStream(bytes);
+ out = new DroolsObjectOutputStream( bytes );
}
+ out.writeObject( this.packageScopeClassLoader.getStore() );
out.writeObject( this.dialectDatas );
out.writeObject( this.typeDeclarations );
out.writeObject( this.name );
@@ -170,30 +224,42 @@
out.writeBoolean( this.valid );
out.writeObject( this.rules );
// writing the whole stream as a byte array
- if (!isDroolsStream) {
+ if ( !isDroolsStream ) {
bytes.flush();
bytes.close();
- stream.writeObject(bytes.toByteArray());
+ stream.writeObject( bytes.toByteArray() );
}
}
/**
- * Handles the read serialization of the Package. Patterns in Rules may reference generated data which cannot be serialized by default methods.
- * The Package uses PackageCompilationData to hold a reference to the generated bytecode; which must be restored before any Rules.
- * A custom ObjectInputStream, able to resolve classes against the bytecode in the PackageCompilationData, is used to restore the Rules.
- * @param stream, the stream to read data from in order to restore the object; should be an instance of
- * DroolsObjectInputStream or InputStream
- *
+ * Handles the read serialization of the Package. Patterns in Rules may
+ * reference generated data which cannot be serialized by default methods.
+ * The Package uses PackageCompilationData to hold a reference to the
+ * generated bytecode; which must be restored before any Rules. A custom
+ * ObjectInputStream, able to resolve classes against the bytecode in the
+ * PackageCompilationData, is used to restore the Rules.
+ *
+ * @param stream,
+ * the stream to read data from in order to restore the object;
+ * should be an instance of DroolsObjectInputStream or
+ * InputStream
+ *
*/
public void readExternal(ObjectInput stream) throws IOException,
- ClassNotFoundException {
- boolean isDroolsStream = stream instanceof DroolsObjectInputStream;
- ObjectInput in = isDroolsStream
- ? stream
- : new DroolsObjectInputStream(new ByteArrayInputStream((byte[])stream.readObject()));
+ ClassNotFoundException {
+ boolean isDroolsStream = stream instanceof DroolsObjectInputStream;
+ DroolsObjectInputStream in = isDroolsStream ? (DroolsObjectInputStream) stream : new DroolsObjectInputStream( new ByteArrayInputStream( (byte[]) stream.readObject() ) );
- this.dialectDatas = (DialectDatas)in.readObject();
- this.typeDeclarations = (Map)in.readObject();
+ // creating package scoped classloader
+ Map store = (Map) in.readObject();
+ this.packageScopeClassLoader = new MapBackedClassLoader( in.getClassLoader(),
+ store );
+
+ // setting parent classloader for dialect datas
+ in.setClassLoader( this.packageScopeClassLoader );
+ this.dialectDatas = (DialectDatas) in.readObject();
+
+ this.typeDeclarations = (Map) in.readObject();
this.name = (String) in.readObject();
this.imports = (Map<String, ImportDeclaration>) in.readObject();
this.staticImports = (Set) in.readObject();
@@ -204,7 +270,10 @@
this.valid = in.readBoolean();
this.rules = (Map) in.readObject();
- if (!isDroolsStream) {
+ // restoring original parent classloader
+ in.setClassLoader( this.packageScopeClassLoader.getParent() );
+
+ if ( !isDroolsStream ) {
in.close();
}
}
@@ -215,7 +284,7 @@
/**
* Retrieve the name of this <code>Package</code>.
- *
+ *
* @return The name of this <code>Package</code>.
*/
public String getName() {
@@ -238,20 +307,21 @@
public Map<String, ImportDeclaration> getImports() {
return this.imports;
}
-
- public void addTypeDeclaration( final TypeDeclaration typeDecl ) {
- this.typeDeclarations.put( typeDecl.getTypeName(), typeDecl );
+
+ public void addTypeDeclaration(final TypeDeclaration typeDecl) {
+ this.typeDeclarations.put( typeDecl.getTypeName(),
+ typeDecl );
}
-
- public void removeTypeDeclaration( final String type ) {
+
+ public void removeTypeDeclaration(final String type) {
this.typeDeclarations.remove( type );
}
-
+
public Map<String, TypeDeclaration> getTypeDeclarations() {
return this.typeDeclarations;
}
-
- public TypeDeclaration getTypeDeclaration( String type ) {
+
+ public TypeDeclaration getTypeDeclaration(String type) {
return this.typeDeclarations.get( type );
}
@@ -269,7 +339,7 @@
this.functions.put( function.getName(),
function );
- dialectDatas.getDialectData(function.getDialect()).setDirty(true);
+ dialectDatas.getDialectData( function.getDialect() ).setDirty( true );
}
public Map<String, Function> getFunctions() {
@@ -323,10 +393,10 @@
/**
* Add a <code>Rule</code> to this <code>Package</code>.
- *
+ *
* @param rule
* The rule to add.
- *
+ *
* @throws DuplicateRuleNameException
* If the <code>Rule</code> attempting to be added has the
* same name as another previously added <code>Rule</code>.
@@ -353,8 +423,8 @@
}
/**
- * Get the rule flows for this package. The key is the ruleflow id.
- * It will be Collections.EMPTY_MAP if none have been added.
+ * Get the rule flows for this package. The key is the ruleflow id. It will
+ * be Collections.EMPTY_MAP if none have been added.
*/
public Map getRuleFlows() {
return this.ruleFlows;
@@ -374,54 +444,61 @@
this.rules.remove( rule.getName() );
this.dialectDatas.removeRule( this,
rule );
- // final String consequenceName = rule.getConsequence().getClass().getName();
+ // final String consequenceName =
+ // rule.getConsequence().getClass().getName();
//
- // Object object = this.dialectData.getDialectData( rule.getDialect() );
+ // Object object = this.dialectData.getDialectData( rule.getDialect() );
//
- // // check for compiled code and remove if present.
- // if ( this.packageCompilationData.remove( consequenceName ) ) {
- // removeClasses( rule.getLhs() );
+ // // check for compiled code and remove if present.
+ // if ( this.packageCompilationData.remove( consequenceName ) ) {
+ // removeClasses( rule.getLhs() );
//
- // // Now remove the rule class - the name is a subset of the consequence name
- // this.packageCompilationData.remove( consequenceName.substring( 0,
- // consequenceName.indexOf( "ConsequenceInvoker" ) ) );
- // }
- // return this.packageCompilationData;
+ // // Now remove the rule class - the name is a subset of the
+ // consequence name
+ // this.packageCompilationData.remove( consequenceName.substring( 0,
+ // consequenceName.indexOf( "ConsequenceInvoker" ) ) );
+ // }
+ // return this.packageCompilationData;
}
- // private void removeClasses(final ConditionalElement ce) {
- // if ( ce instanceof GroupElement ) {
- // final GroupElement group = (GroupElement) ce;
- // for ( final Iterator it = group.getChildren().iterator(); it.hasNext(); ) {
- // final Object object = it.next();
- // if ( object instanceof ConditionalElement ) {
- // removeClasses( (ConditionalElement) object );
- // } else if ( object instanceof Pattern ) {
- // removeClasses( (Pattern) object );
- // }
- // }
- // } else if ( ce instanceof EvalCondition ) {
- // this.packageCompilationData.remove( ((EvalCondition) ce).getEvalExpression().getClass().getName() );
- // }
- // }
+ // private void removeClasses(final ConditionalElement ce) {
+ // if ( ce instanceof GroupElement ) {
+ // final GroupElement group = (GroupElement) ce;
+ // for ( final Iterator it = group.getChildren().iterator(); it.hasNext(); )
+ // {
+ // final Object object = it.next();
+ // if ( object instanceof ConditionalElement ) {
+ // removeClasses( (ConditionalElement) object );
+ // } else if ( object instanceof Pattern ) {
+ // removeClasses( (Pattern) object );
+ // }
+ // }
+ // } else if ( ce instanceof EvalCondition ) {
+ // this.packageCompilationData.remove( ((EvalCondition)
+ // ce).getEvalExpression().getClass().getName() );
+ // }
+ // }
//
- // private void removeClasses(final Pattern pattern) {
- // for ( final Iterator it = pattern.getConstraints().iterator(); it.hasNext(); ) {
- // final Object object = it.next();
- // if ( object instanceof PredicateConstraint ) {
- // this.packageCompilationData.remove( ((PredicateConstraint) object).getPredicateExpression().getClass().getName() );
- // } else if ( object instanceof ReturnValueConstraint ) {
- // this.packageCompilationData.remove( ((ReturnValueConstraint) object).getExpression().getClass().getName() );
- // }
- // }
- // }
+ // private void removeClasses(final Pattern pattern) {
+ // for ( final Iterator it = pattern.getConstraints().iterator();
+ // it.hasNext(); ) {
+ // final Object object = it.next();
+ // if ( object instanceof PredicateConstraint ) {
+ // this.packageCompilationData.remove( ((PredicateConstraint)
+ // object).getPredicateExpression().getClass().getName() );
+ // } else if ( object instanceof ReturnValueConstraint ) {
+ // this.packageCompilationData.remove( ((ReturnValueConstraint)
+ // object).getExpression().getClass().getName() );
+ // }
+ // }
+ // }
/**
* Retrieve a <code>Rule</code> by name.
- *
+ *
* @param name
* The name of the <code>Rule</code> to retrieve.
- *
+ *
* @return The named <code>Rule</code>, or <code>null</code> if not
* such <code>Rule</code> has been added to this
* <code>Package</code>.
@@ -432,16 +509,16 @@
/**
* Retrieve all <code>Rules</code> in this <code>Package</code>.
- *
+ *
* @return An array of all <code>Rules</code> in this <code>Package</code>.
*/
public Rule[] getRules() {
return (Rule[]) this.rules.values().toArray( new Rule[this.rules.size()] );
}
- // public JavaDialectData getPackageCompilationData() {
- // return this.packageCompilationData;
- // }
+ // public JavaDialectData getPackageCompilationData() {
+ // return this.packageCompilationData;
+ // }
public String toString() {
return "[Package name=" + this.name + "]";
@@ -494,6 +571,7 @@
/**
* Returns true if clazz is imported as an Event class in this package
+ *
* @param clazz
* @return true if clazz is imported as an Event class in this package
*/
@@ -503,8 +581,8 @@
}
// check if clazz is resolved by any of the type declarations
- for( TypeDeclaration type : this.typeDeclarations.values() ) {
- if( type.matches( clazz ) && type.getRole() == TypeDeclaration.Role.EVENT ) {
+ for ( TypeDeclaration type : this.typeDeclarations.values() ) {
+ if ( type.matches( clazz ) && type.getRole() == TypeDeclaration.Role.EVENT ) {
return true;
}
}
@@ -525,12 +603,17 @@
}
public FactType getFactType(final String typeName) {
- if( this.name != null && ! typeName.startsWith( this.name ) ) {
+ if ( this.name != null && !typeName.startsWith( this.name ) ) {
return null;
}
- // in case the package name is != null, remove the package name from the beginning of the type name
- String key = this.name == null ? typeName : typeName.substring( this.name.length()+1 );
- TypeDeclaration decl = this.typeDeclarations.get( key );
+ // in case the package name is != null, remove the package name from the
+ // beginning of the type name
+ String key = this.name == null ? typeName : typeName.substring( this.name.length() + 1 );
+ TypeDeclaration decl = this.typeDeclarations.get( key );
return decl != null ? decl.getTypeClassDef() : null;
}
+
+ public MapBackedClassLoader getPackageScopeClassLoader() {
+ return packageScopeClassLoader;
+ }
}
\ No newline at end of file
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/asm/ClassFieldInspector.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/asm/ClassFieldInspector.java 2008-05-24 13:51:11 UTC (rev 20154)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/asm/ClassFieldInspector.java 2008-05-24 18:01:50 UTC (rev 20155)
@@ -26,6 +26,7 @@
import java.util.Map;
import java.util.Set;
+import org.drools.RuntimeDroolsException;
import org.drools.asm.AnnotationVisitor;
import org.drools.asm.Attribute;
import org.drools.asm.ClassReader;
@@ -33,6 +34,7 @@
import org.drools.asm.FieldVisitor;
import org.drools.asm.MethodVisitor;
import org.drools.asm.Opcodes;
+import org.drools.asm.Type;
/**
* Visit a POJO user class, and extract the property getter methods that are public, in the
@@ -121,22 +123,22 @@
for ( int i = 0; i < methods.length; i++ ) {
// modifiers mask
final int mask = includeFinalMethods ? Modifier.PUBLIC : Modifier.PUBLIC | Modifier.FINAL;
-
- if ( ((methods[i].getModifiers() & mask) == Opcodes.ACC_PUBLIC ) && (methods[i].getParameterTypes().length == 0) && (!methods[i].getName().equals( "<init>" )) && (!methods[i].getName().equals( "<clinit>" ))
+
+ if ( ((methods[i].getModifiers() & mask) == Opcodes.ACC_PUBLIC) && (methods[i].getParameterTypes().length == 0) && (!methods[i].getName().equals( "<init>" )) && (!methods[i].getName().equals( "<clinit>" ))
&& (methods[i].getReturnType() != void.class) ) {
-
+
// want public methods that start with 'get' or 'is' and have no args, and return a value
final int fieldIndex = this.fieldNames.size();
addToMapping( methods[i],
fieldIndex );
-
- } else if ( ((methods[i].getModifiers() & mask) == Opcodes.ACC_PUBLIC ) && (methods[i].getParameterTypes().length == 1) && (methods[i].getName().startsWith( "set" ))) {
+ } else if ( ((methods[i].getModifiers() & mask) == Opcodes.ACC_PUBLIC) && (methods[i].getParameterTypes().length == 1) && (methods[i].getName().startsWith( "set" )) ) {
+
// want public methods that start with 'set' and have one arg
final int fieldIndex = this.fieldNames.size();
addToMapping( methods[i],
fieldIndex );
-
+
}
}
}
@@ -211,7 +213,7 @@
fieldName );
storeGetterSetter( method,
fieldName );
-
+
if ( offset == 0 ) {
// only if it is a non-standard getter method
this.nonGetters.add( fieldName );
@@ -240,15 +242,15 @@
*/
private void storeGetterSetter(final Method method,
final String fieldName) {
- if( method.getName().startsWith( "set" ) ) {
+ if ( method.getName().startsWith( "set" ) ) {
this.setterMethods.put( fieldName,
method );
- if( ! fieldTypes.containsKey( fieldName ) ) {
+ if ( !fieldTypes.containsKey( fieldName ) ) {
this.fieldTypes.put( fieldName,
method.getParameterTypes()[0] );
}
} else {
- this.getterMethods.put( fieldName,
+ this.getterMethods.put( fieldName,
method );
this.fieldTypes.put( fieldName,
method.getReturnType() );
@@ -290,20 +292,28 @@
//and have no args, and return a value
final int mask = this.includeFinalMethods ? Opcodes.ACC_PUBLIC : Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL;
if ( (access & mask) == Opcodes.ACC_PUBLIC ) {
- if (( desc.startsWith( "()" ) && (!name.equals( "<init>" )) && (!name.equals( "<clinit>" )) ) ||
- ( name.startsWith( "set" ) ) ){// && ( name.startsWith("get") || name.startsWith("is") ) ) {
- try {
+ try {
+ if ( desc.startsWith( "()" ) && (!name.equals( "<init>" )) && (!name.equals( "<clinit>" )) ) {// && ( name.startsWith("get") || name.startsWith("is") ) ) {
final Method method = this.clazz.getMethod( name,
(Class[]) null );
- if ( method.getReturnType() != void.class ||
- ( method.getName().startsWith( "set" ) && ( method.getParameterTypes().length == 1 ) ) ) {
+ if ( method.getReturnType() != void.class ) {
final int fieldIndex = this.inspector.fieldNames.size();
this.inspector.addToMapping( method,
fieldIndex );
}
- } catch ( final NoSuchMethodException e ) {
- throw new IllegalStateException( "Error in getting field access method." );
+ } else if ( name.startsWith( "set" ) ) {
+ // I found no safe way of getting the method object from the descriptor, so doing the other way around
+ Method[] methods = this.clazz.getMethods();
+ for( int i = 0; i < methods.length; i++ ) {
+ if( desc.equals( Type.getMethodDescriptor( methods[i] ) ) ) {
+ final int fieldIndex = this.inspector.fieldNames.size();
+ this.inspector.addToMapping( methods[i],
+ fieldIndex );
+ }
+ }
}
+ } catch ( final Exception e ) {
+ throw new RuntimeDroolsException( "Error getting field access method: "+name+": "+e.getMessage(), e );
}
}
return null;
More information about the jboss-svn-commits
mailing list