Skip to content

Commit

Permalink
JBRULES-3257: storing ObjectMarshallingStrategy type based on classNa…
Browse files Browse the repository at this point in the history
…me, not store index
  • Loading branch information
Marco Rietveld committed Oct 22, 2011
1 parent 1133bea commit 06fc7a1
Show file tree
Hide file tree
Showing 17 changed files with 1,646 additions and 954 deletions.
1 change: 1 addition & 0 deletions drools-compiler/.gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/target
/local
/bin

# Eclipse, Netbeans and IntelliJ files
/.*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.drools.integrationtests;

import static java.lang.System.out;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
Expand Down Expand Up @@ -71,22 +72,14 @@ public static StatefulSession getSerialisedStatefulSession(StatefulSession sessi
out.close();
bos.close();

// System.out.println( "bos:\n" + bos.toByteArray() );
// if ( true ) {
// byte[] b1 = bos.toByteArray();
// for ( int i = 0, length = b1.length; i < length; i++ ) {
// System.out.print( b1[i] );
// }
// throw new IllegalArgumentException( "byte streams for serialisation test are not equal" );
// }

// Get the bytes of the serialized object
final byte[] b1 = bos.toByteArray();

ByteArrayInputStream bais = new ByteArrayInputStream( b1 );
StatefulSession session2 = ruleBase.newStatefulSession( bais );
bais.close();

// Reserialize and check that byte arrays are the same
bos = new ByteArrayOutputStream();
out = new ObjectOutputStream( bos );
out.writeObject( session2 );
Expand Down Expand Up @@ -116,28 +109,40 @@ public static StatefulKnowledgeSession getSerialisedStatefulKnowledgeSession(Sta
boolean dispose) throws Exception {

DefaultMarshaller marshaller = ( DefaultMarshaller ) MarshallerFactory.newMarshaller( ksession.getKnowledgeBase(),
(ObjectMarshallingStrategy[])ksession.getEnvironment().get(EnvironmentName.OBJECT_MARSHALLING_STRATEGIES) );

(ObjectMarshallingStrategy[])ksession.getEnvironment().get(EnvironmentName.OBJECT_MARSHALLING_STRATEGIES) );
long time = ksession.getSessionClock().getCurrentTime();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
marshaller.marshall( bos,
ksession,
time );
final byte[] b1 = bos.toByteArray();
bos.close();

ByteArrayInputStream bais = new ByteArrayInputStream( b1 );
StatefulKnowledgeSession ksession2 = marshaller.unmarshall( bais,
new SessionConfiguration(),
ksession.getEnvironment());
bais.close();

bos = new ByteArrayOutputStream();
marshaller.marshall( bos,
ksession2,
time );
final byte[] b2 = bos.toByteArray();
bos.close();
// Serialize object
final byte [] b1;
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
marshaller.marshall( bos,
ksession,
time );
b1 = bos.toByteArray();
bos.close();
}

// Deserialize object
StatefulKnowledgeSession ksession2;
{
ByteArrayInputStream bais = new ByteArrayInputStream( b1 );
ksession2 = marshaller.unmarshall( bais,
new SessionConfiguration(),
ksession.getEnvironment());
bais.close();
}

// Reserialize and check that byte arrays are the same
final byte[] b2;
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
marshaller.marshall( bos,
ksession2,
time );
b2 = bos.toByteArray();
bos.close();
}

// bytes should be the same.
if ( !areByteArraysEqual( b1,
Expand Down Expand Up @@ -182,9 +187,8 @@ public static boolean areByteArraysEqual(byte[] b1,
// if ( i == 83 ) {
// System.out.print( "!" );
// }

// }
System.out.println( "\n" );

for ( int i = 0, length = b1.length; i < length; i++ ) {
if ( b1[i] != b2[i] ) {
System.out.println( "Difference at " + i + ": [" + b1[i] + "] != [" + b2[i] + "]" );
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package org.drools.integrationtests.marshalling;

import static org.junit.Assert.assertTrue;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.Date;

import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseConfiguration;
import org.drools.KnowledgeBaseFactory;
import org.drools.Person;
import org.drools.RuleBase;
import org.drools.SessionConfiguration;
import org.drools.common.AbstractWorkingMemory;
import org.drools.common.DefaultFactHandle;
import org.drools.common.EventFactHandle;
import org.drools.common.InternalFactHandle;
import org.drools.common.InternalRuleBase;
import org.drools.common.NamedEntryPoint;
import org.drools.common.RuleBasePartitionId;
import org.drools.conf.EventProcessingOption;
import org.drools.impl.EnvironmentFactory;
import org.drools.impl.KnowledgeBaseImpl;
import org.drools.integrationtests.marshalling.util.OldOutputMarshallerMethods;
import org.drools.marshalling.MarshallerFactory;
import org.drools.marshalling.ObjectMarshallingStrategy;
import org.drools.marshalling.impl.InputMarshaller;
import org.drools.marshalling.impl.MarshallerProviderImpl;
import org.drools.marshalling.impl.MarshallerReaderContext;
import org.drools.marshalling.impl.MarshallerWriteContext;
import org.drools.marshalling.impl.ObjectMarshallingStrategyStore;
import org.drools.reteoo.EntryPointNode;
import org.drools.reteoo.ObjectSource;
import org.drools.reteoo.Rete;
import org.drools.reteoo.ReteooRuleBase;
import org.drools.reteoo.ReteooWorkingMemory;
import org.drools.rule.EntryPoint;
import org.drools.runtime.KnowledgeSessionConfiguration;
import org.drools.runtime.conf.ClockTypeOption;
import org.drools.runtime.rule.WorkingMemoryEntryPoint;
import org.junit.Assert;
import org.junit.Test;

public class FactHandleMarshallingTest {

private RuleBase createRuleBase() {
KnowledgeBaseConfiguration config = KnowledgeBaseFactory.newKnowledgeBaseConfiguration();
config.setOption( EventProcessingOption.STREAM );
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase( config );
RuleBase ruleBase = ((KnowledgeBaseImpl) kbase).getRuleBase();
return ruleBase;
}

private InternalFactHandle createEventFactHandle(AbstractWorkingMemory wm, RuleBase ruleBase) {
// EntryPointNode
Rete rete = ((ReteooRuleBase) ruleBase).getRete();
RuleBasePartitionId partionId = new RuleBasePartitionId("P-MAIN");
EntryPointNode entryPointNode = new EntryPointNode(1, partionId, false, (ObjectSource) rete , EntryPoint.DEFAULT);
WorkingMemoryEntryPoint wmEntryPoint = new NamedEntryPoint(EntryPoint.DEFAULT, entryPointNode, wm);
EventFactHandle factHandle = new EventFactHandle(1, (Object) new Person(),0, (new Date()).getTime(), 0, wmEntryPoint);

return factHandle;
}

private AbstractWorkingMemory createWorkingMemory(RuleBase ruleBase) {
// WorkingMemoryEntryPoint
KnowledgeSessionConfiguration ksconf = KnowledgeBaseFactory.newKnowledgeSessionConfiguration();
ksconf.setOption( ClockTypeOption.get( "pseudo" ) );
SessionConfiguration sessionConf = ((SessionConfiguration) ksconf);
AbstractWorkingMemory wm = new ReteooWorkingMemory(1, (InternalRuleBase) ruleBase,
sessionConf, EnvironmentFactory.newEnvironment());

return wm;
}

@Test
public void backwardsCompatibleEventFactHandleTest() throws IOException, ClassNotFoundException {
RuleBase ruleBase = createRuleBase();
AbstractWorkingMemory wm = createWorkingMemory(ruleBase);
InternalFactHandle factHandle = createEventFactHandle(wm, ruleBase);

// marshall/serialize workItem
byte [] byteArray;
{
ObjectMarshallingStrategy[] strats
= new ObjectMarshallingStrategy[] {
MarshallerFactory.newSerializeMarshallingStrategy(),
new MarshallerProviderImpl().newIdentityMarshallingStrategy() };

ByteArrayOutputStream baos = new ByteArrayOutputStream();
MarshallerWriteContext outContext = new MarshallerWriteContext( baos, null, null, null,
new ObjectMarshallingStrategyStore(strats), true, true, null);
OldOutputMarshallerMethods.writeFactHandle_v1(outContext, (ObjectOutputStream) outContext,
outContext.objectMarshallingStrategyStore, 2, factHandle);
outContext.close();
byteArray = baos.toByteArray();
}

// unmarshall/deserialize workItem
InternalFactHandle newFactHandle;
{
// Only put serialization strategy in
ObjectMarshallingStrategy[] newStrats
= new ObjectMarshallingStrategy[] {
MarshallerFactory.newSerializeMarshallingStrategy() };

ByteArrayInputStream bais = new ByteArrayInputStream(byteArray);
MarshallerReaderContext inContext = new MarshallerReaderContext( bais, null, null,
new ObjectMarshallingStrategyStore(newStrats), true, true, null);
inContext.wm = wm;
newFactHandle = InputMarshaller.readFactHandle(inContext);
inContext.close();
}

assertTrue( "Serialized FactHandle not the same as the original.", compareInstances(factHandle, newFactHandle) );
}

private boolean compareInstances(Object objA, Object objB) {
boolean same = true;
if( objA != null && objB != null ) {
if( ! objA.getClass().equals(objB.getClass()) ) {
return false;
}
String className = objA.getClass().getName();
if( className.startsWith("java") ) {
return objA.equals(objB);
}

try {
Field [] fields = objA.getClass().getDeclaredFields();
if( fields.length == 0 ) {
same = true;
}
else {
for( int i = 0; same && i < fields.length; ++i ) {
fields[i].setAccessible(true);
Object subObjA = fields[i].get(objA);
Object subObjB = fields[i].get(objB);
if( ! compareInstances(subObjA, subObjB) ) {
return false;
}
}
}
}
catch( Exception e ) {
same = false;
Assert.fail(e.getClass().getSimpleName() + ":" + e.getMessage() );
}
}
else if( objA != objB ) {
return false;
}

return same;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package org.drools.integrationtests.marshalling;

import static org.junit.Assert.assertTrue;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Date;

import org.junit.Test;

/**
* Should Drools ever need it, this test shows who we can implement peak using a {@link BufferedInputStream}
* in combination with an {@link ObjectInputStream}.
*
* If you come across this and want to delete it, go ahead. Hopefully we'll never need the code.
*/
public class InputStreamMarkResetTest {

@Test
public void basicReadAndWriteObjectTest() throws Exception {

DataObject thingy = new DataObject();
thingy.type = 'a';
thingy.time = new Date().getTime();
thingy.strCount = "1";

byte [] bytes = marshallThingy(thingy);


ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
BufferedInputStream bis = new BufferedInputStream(bais);
ObjectInputStream stream = new ObjectInputStream(bis);

DataObject unmaThingy = new DataObject();
unmaThingy.type = stream.readChar();
unmaThingy.time = stream.readLong();

assertTrue( "Mark/reset is not supported", bis.markSupported() );
bis.mark(8);
int [] intBytes = new int [4];
intBytes[0] = bis.read();
intBytes[1] = bis.read();
intBytes[2] = bis.read();
intBytes[3] = bis.read();
if ((intBytes[0] | intBytes[1] | intBytes[2] | intBytes[3] ) < 0) {
bis.reset();
}
unmaThingy.strCount = stream.readUTF();

assertTrue( thingy.equals(unmaThingy) );
}

private byte [] marshallThingy(DataObject thingy ) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream stream = new ObjectOutputStream(baos);

stream.writeChar(thingy.type);
stream.writeLong(thingy.time);
if( thingy.intCount != null ) {
stream.writeInt(thingy.intCount);
}
else if( thingy.strCount != null ) {
stream.writeUTF(thingy.strCount);
}
else {
throw new IllegalStateException("Neither the integer nor String count is filled." );
}
stream.close();

return baos.toByteArray();
}

private class DataObject {
char type;
long time;

// one or the other..
Integer intCount;
String strCount;

@Override
public boolean equals(Object obj) {
if( obj == null ) {
return false;
}
if( ! this.getClass().equals(obj.getClass()) ) {
return false;
}
else {
DataObject newThingy = (DataObject) obj;
if( this.type != newThingy.type ) {
return false;
}
if( this.time != newThingy.time ) {
return false;
}
Integer count = null;
if( this.intCount != null ) {
count = this.intCount;
}
else {
count = Integer.parseInt(this.strCount);
}
Integer newCount = null;
if( newThingy.intCount != null ) {
newCount = newThingy.intCount;
}
else {
newCount = Integer.parseInt(newThingy.strCount);
}
if( count != null && newCount != null ) {
if( ! count.equals(newCount) ) {
return false;
}
}
else if( count != newCount ) {
return false;
}
}
return true;
}
}
}
Loading

0 comments on commit 06fc7a1

Please sign in to comment.