[BZ-1044577] implement CommandBasedWorkingMemoryEntryPoint
diff --git a/drools-core/src/main/java/org/drools/command/WorkingMemoryEntryPointBuilder.java b/drools-core/src/main/java/org/drools/command/WorkingMemoryEntryPointBuilder.java
new file mode 100644
index 0000000..3010215
--- /dev/null
+++ b/drools-core/src/main/java/org/drools/command/WorkingMemoryEntryPointBuilder.java
@@ -0,0 +1,9 @@
+package org.drools.command;
+
+import org.drools.runtime.StatefulKnowledgeSession;
+import org.drools.runtime.rule.WorkingMemoryEntryPoint;
+
+public interface WorkingMemoryEntryPointBuilder {
+
+    WorkingMemoryEntryPoint getWorkingMemoryEntryPoint(String entryPoint);
+}
diff --git a/drools-core/src/main/java/org/drools/command/impl/CommandBasedStatefulKnowledgeSession.java b/drools-core/src/main/java/org/drools/command/impl/CommandBasedStatefulKnowledgeSession.java
index 175150d..760eb7a 100644
--- a/drools-core/src/main/java/org/drools/command/impl/CommandBasedStatefulKnowledgeSession.java
+++ b/drools-core/src/main/java/org/drools/command/impl/CommandBasedStatefulKnowledgeSession.java
@@ -24,7 +24,6 @@
 import org.drools.KnowledgeBase;
 import org.drools.command.Command;
 import org.drools.command.CommandService;
-import org.drools.command.ExecuteCommand;
 import org.drools.command.GetSessionClockCommand;
 import org.drools.command.Interceptor;
 import org.drools.command.runtime.AddEventListenerCommand;
@@ -32,6 +31,7 @@
 import org.drools.command.runtime.GetCalendarsCommand;
 import org.drools.command.runtime.GetChannelsCommand;
 import org.drools.command.runtime.GetEnvironmentCommand;
+import org.drools.command.runtime.GetFactCountCommand;
 import org.drools.command.runtime.GetGlobalCommand;
 import org.drools.command.runtime.GetGlobalsCommand;
 import org.drools.command.runtime.GetIdCommand;
@@ -77,7 +77,6 @@
 import org.drools.event.process.ProcessEventListener;
 import org.drools.event.rule.AgendaEventListener;
 import org.drools.event.rule.WorkingMemoryEventListener;
-import org.drools.impl.StatefulKnowledgeSessionImpl.AgendaFilterWrapper;
 import org.drools.process.instance.WorkItem;
 import org.drools.process.instance.WorkItemManager;
 import org.drools.rule.EntryPoint;
@@ -495,8 +494,7 @@
     }
 
     public long getFactCount() {
-        // TODO: implement this
-        return 0;
+        return commandService.execute( new GetFactCountCommand());
     }
 
     public LiveQuery openLiveQuery(String query,
diff --git a/drools-core/src/main/java/org/drools/command/impl/CommandBasedWorkingMemoryEntryPoint.java b/drools-core/src/main/java/org/drools/command/impl/CommandBasedWorkingMemoryEntryPoint.java
new file mode 100644
index 0000000..aa10fe6
--- /dev/null
+++ b/drools-core/src/main/java/org/drools/command/impl/CommandBasedWorkingMemoryEntryPoint.java
@@ -0,0 +1,72 @@
+package org.drools.command.impl;
+
+import org.drools.command.CommandService;
+import org.drools.command.runtime.GetFactCountInEntryPointCommand;
+import org.drools.command.runtime.rule.GetFactHandleInEntryPointCommand;
+import org.drools.command.runtime.rule.GetFactHandlesInEntryPointCommand;
+import org.drools.command.runtime.rule.GetObjectInEntryPointCommand;
+import org.drools.command.runtime.rule.GetObjectsInEntryPointCommand;
+import org.drools.command.runtime.rule.InsertObjectCommand;
+import org.drools.command.runtime.rule.InsertObjectInEntryPointCommand;
+import org.drools.command.runtime.rule.RetractFromEntryPointCommand;
+import org.drools.command.runtime.rule.UpdateInEntryPointCommand;
+import org.drools.runtime.ObjectFilter;
+import org.drools.runtime.rule.FactHandle;
+import org.drools.runtime.rule.WorkingMemoryEntryPoint;
+
+import java.util.Collection;
+
+public class CommandBasedWorkingMemoryEntryPoint implements WorkingMemoryEntryPoint {
+
+    private final CommandService commandService;
+    private final String entryPoint;
+
+    public CommandBasedWorkingMemoryEntryPoint(CommandService commandService, String entryPoint) {
+        this.commandService = commandService;
+        this.entryPoint = entryPoint;
+    }
+
+    public String getEntryPointId() {
+        return entryPoint;
+    }
+
+    public FactHandle insert(Object object) {
+        return commandService.execute( new InsertObjectInEntryPointCommand( object, entryPoint ) );
+    }
+
+    public void retract(FactHandle handle) {
+        commandService.execute( new RetractFromEntryPointCommand( handle, entryPoint ) );
+    }
+
+    public void update(FactHandle handle, Object object) {
+        commandService.execute( new UpdateInEntryPointCommand( handle, object, entryPoint ) );
+    }
+
+    public FactHandle getFactHandle(Object object) {
+        return commandService.execute( new GetFactHandleInEntryPointCommand(object, entryPoint) );
+    }
+
+    public Object getObject(FactHandle factHandle) {
+        return commandService.execute( new GetObjectInEntryPointCommand(factHandle, entryPoint) );
+    }
+
+    public Collection<Object> getObjects() {
+        return commandService.execute( new GetObjectsInEntryPointCommand(null, entryPoint) );
+    }
+
+    public Collection<Object> getObjects(ObjectFilter filter) {
+        return commandService.execute( new GetObjectsInEntryPointCommand(filter, entryPoint) );
+    }
+
+    public <T extends FactHandle> Collection<T> getFactHandles() {
+        return (Collection<T>) commandService.execute( new GetFactHandlesInEntryPointCommand(entryPoint) );
+    }
+
+    public <T extends FactHandle> Collection<T> getFactHandles(ObjectFilter filter) {
+        return (Collection<T>) commandService.execute( new GetFactHandlesInEntryPointCommand(entryPoint, filter) );
+    }
+
+    public long getFactCount() {
+        return commandService.execute( new GetFactCountInEntryPointCommand(entryPoint) );
+    }
+}
diff --git a/drools-core/src/main/java/org/drools/command/runtime/GetFactCountInEntryPointCommand.java b/drools-core/src/main/java/org/drools/command/runtime/GetFactCountInEntryPointCommand.java
new file mode 100644
index 0000000..2201eeb
--- /dev/null
+++ b/drools-core/src/main/java/org/drools/command/runtime/GetFactCountInEntryPointCommand.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2010 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.command.runtime;
+
+import org.drools.command.Context;
+import org.drools.command.impl.GenericCommand;
+import org.drools.command.impl.KnowledgeCommandContext;
+import org.drools.runtime.StatefulKnowledgeSession;
+
+public class GetFactCountInEntryPointCommand
+    implements
+    GenericCommand<Long> {
+
+    private String entryPoint;
+
+    public GetFactCountInEntryPointCommand(String entryPoint) {
+        this.entryPoint = entryPoint;
+    }
+
+    public Long execute(Context context) {
+        StatefulKnowledgeSession ksession = ((KnowledgeCommandContext) context).getStatefulKnowledgesession();
+        return ksession.getWorkingMemoryEntryPoint(entryPoint).getFactCount();
+    }
+
+    public String toString() {
+        return "ksession.getWorkingMemoryEntryPoint(" + entryPoint + ").getFactCount();";
+    }
+
+}
diff --git a/drools-core/src/main/java/org/drools/command/runtime/rule/GetFactHandleInEntryPointCommand.java b/drools-core/src/main/java/org/drools/command/runtime/rule/GetFactHandleInEntryPointCommand.java
new file mode 100644
index 0000000..8f0a35a
--- /dev/null
+++ b/drools-core/src/main/java/org/drools/command/runtime/rule/GetFactHandleInEntryPointCommand.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2010 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.command.runtime.rule;
+
+import org.drools.command.Context;
+import org.drools.command.impl.GenericCommand;
+import org.drools.command.impl.KnowledgeCommandContext;
+import org.drools.common.InternalFactHandle;
+import org.drools.runtime.StatefulKnowledgeSession;
+import org.drools.runtime.rule.FactHandle;
+import org.drools.runtime.rule.WorkingMemoryEntryPoint;
+
+public class GetFactHandleInEntryPointCommand
+    implements
+    GenericCommand<FactHandle> {
+
+    private Object object;
+    private boolean disconnected;
+    private String entryPoint;
+
+    public GetFactHandleInEntryPointCommand(Object object, String entryPoint) {
+        this(object, entryPoint, false);
+    }
+
+    public GetFactHandleInEntryPointCommand(Object object, String entryPoint, boolean disconnected) {
+        this.object = object;
+        this.entryPoint = entryPoint;
+        this.disconnected = disconnected;
+    }
+
+    public FactHandle execute(Context context) {
+        StatefulKnowledgeSession ksession = ((KnowledgeCommandContext) context).getStatefulKnowledgesession();
+        WorkingMemoryEntryPoint ep = ksession.getWorkingMemoryEntryPoint(entryPoint);
+        InternalFactHandle factHandle = (InternalFactHandle) ep.getFactHandle( object );
+        if ( factHandle != null ){
+            InternalFactHandle handle = factHandle.clone();
+            if ( disconnected ) {
+                handle.disconnect();
+            }
+            return handle;
+        }
+        return null;
+    }
+
+    public String toString() {
+        return "ksession.getWorkingMemoryEntryPoint(" + entryPoint + ").getFactHandle( " + object + " );";
+    }
+}
diff --git a/drools-core/src/main/java/org/drools/command/runtime/rule/GetFactHandlesInEntryPointCommand.java b/drools-core/src/main/java/org/drools/command/runtime/rule/GetFactHandlesInEntryPointCommand.java
new file mode 100644
index 0000000..6dc76e9
--- /dev/null
+++ b/drools-core/src/main/java/org/drools/command/runtime/rule/GetFactHandlesInEntryPointCommand.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2010 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.command.runtime.rule;
+
+import org.drools.command.Context;
+import org.drools.command.impl.GenericCommand;
+import org.drools.command.impl.KnowledgeCommandContext;
+import org.drools.common.InternalFactHandle;
+import org.drools.runtime.ObjectFilter;
+import org.drools.runtime.StatefulKnowledgeSession;
+import org.drools.runtime.rule.FactHandle;
+import org.drools.runtime.rule.WorkingMemoryEntryPoint;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+public class GetFactHandlesInEntryPointCommand
+    implements
+    GenericCommand<Collection<FactHandle>> {
+
+    private ObjectFilter filter = null;
+    private boolean      disconnected = false;
+    private String       entryPoint;
+
+    public GetFactHandlesInEntryPointCommand(String entryPoint) {
+        this.entryPoint = entryPoint;
+    }
+
+    public GetFactHandlesInEntryPointCommand(String entryPoint, ObjectFilter filter) {
+        this.entryPoint = entryPoint;
+        this.filter = filter;
+    }
+
+    public GetFactHandlesInEntryPointCommand(String entryPoint, ObjectFilter filter, boolean disconnected) {
+        this.entryPoint = entryPoint;
+        this.filter = filter;
+        this.disconnected = disconnected;
+    }
+
+    public GetFactHandlesInEntryPointCommand(String entryPoint, boolean disconnected) {
+        this.entryPoint = entryPoint;
+        this.disconnected = disconnected;
+    }
+
+    public Collection<FactHandle> execute(Context context) {
+        StatefulKnowledgeSession ksession = ((KnowledgeCommandContext) context).getStatefulKnowledgesession();
+        WorkingMemoryEntryPoint ep = ksession.getWorkingMemoryEntryPoint(entryPoint);
+        Collection<FactHandle> disconnectedFactHandles = new ArrayList<FactHandle>();
+        if ( filter != null ) {
+            Collection<InternalFactHandle> factHandles = ep.getFactHandles( this.filter );
+            if(factHandles != null && disconnected){
+                for(InternalFactHandle factHandle: factHandles){
+                    InternalFactHandle handle = factHandle.clone();
+                    handle.disconnect();
+                    disconnectedFactHandles.add(handle);
+                }
+                return disconnectedFactHandles;
+            }
+            else { 
+                return ksession.getFactHandles( this.filter );
+            }
+        } else {
+            Collection<InternalFactHandle> factHandles = ep.getFactHandles( );
+            if(factHandles != null && disconnected){
+                for(InternalFactHandle factHandle: factHandles){
+                    InternalFactHandle handle = factHandle.clone();
+                    handle.disconnect();
+                    disconnectedFactHandles.add(handle);
+                }
+                return disconnectedFactHandles;
+            }
+            else { 
+                return ksession.getFactHandles();
+            }
+        }
+    }
+
+    public String toString() {
+        if ( filter != null ) {
+            return "new ObjectStoreWrapper( reteooStatefulSession.getObjectStore(), null, ObjectStoreWrapper.FACT_HANDLE )";
+        } else {
+            return "new ObjectStoreWrapper( reteooStatefulSession.getObjectStore(), filter, ObjectStoreWrapper.FACT_HANDLE )";
+        }
+    }
+}
diff --git a/drools-core/src/main/java/org/drools/command/runtime/rule/GetObjectInEntryPointCommand.java b/drools-core/src/main/java/org/drools/command/runtime/rule/GetObjectInEntryPointCommand.java
new file mode 100644
index 0000000..1eeae0f
--- /dev/null
+++ b/drools-core/src/main/java/org/drools/command/runtime/rule/GetObjectInEntryPointCommand.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2010 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.command.runtime.rule;
+
+import org.drools.command.Context;
+import org.drools.command.impl.GenericCommand;
+import org.drools.command.impl.KnowledgeCommandContext;
+import org.drools.common.DefaultFactHandle;
+import org.drools.impl.StatefulKnowledgeSessionImpl;
+import org.drools.runtime.StatefulKnowledgeSession;
+import org.drools.runtime.rule.FactHandle;
+import org.drools.runtime.rule.WorkingMemoryEntryPoint;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+
+@XmlAccessorType(XmlAccessType.NONE)
+public class GetObjectInEntryPointCommand
+    implements
+    GenericCommand<Object> {
+
+    private FactHandle factHandle;
+    private String     outIdentifier;
+
+    @XmlAttribute(name="entry-point")
+    private String entryPoint;
+
+    public GetObjectInEntryPointCommand() { }
+
+    public GetObjectInEntryPointCommand(FactHandle factHandle, String entryPoint) {
+        this.factHandle = factHandle;
+        this.entryPoint = entryPoint;
+    }
+
+    public GetObjectInEntryPointCommand(FactHandle factHandle, String entryPoint, String outIdentifier) {
+        this.factHandle = factHandle;
+        this.entryPoint = entryPoint;
+        this.outIdentifier = outIdentifier;
+    }
+
+    @XmlAttribute(name="out-identifier", required=true)
+    public String getOutIdentifier() {
+        return outIdentifier;
+    }
+
+    public void setOutIdentifier(String outIdentifier) {
+        this.outIdentifier = outIdentifier;
+    }
+
+    @XmlAttribute(name="fact-handle", required=true)
+    public void setFactHandleFromString(String factHandleId) {
+        factHandle = new DefaultFactHandle(factHandleId);
+    }
+    
+    public String getFactHandleFromString() {
+        return factHandle.toExternalForm();
+    }
+
+    public Object execute(Context context) {
+        StatefulKnowledgeSession ksession = ((KnowledgeCommandContext) context).getStatefulKnowledgesession();
+        WorkingMemoryEntryPoint ep = ksession.getWorkingMemoryEntryPoint(entryPoint);
+        Object object = ep.getObject( factHandle );
+        
+        if (this.outIdentifier != null) {
+            ((StatefulKnowledgeSessionImpl)ksession).session.getExecutionResult()
+                .getResults().put( this.outIdentifier, object );
+        }
+        
+        return object;
+    }
+    
+    public FactHandle getFactHandle() {
+        return this.factHandle;
+    }
+
+    public String toString() {
+        return "session.getWorkingMemoryEntryPoint(" + entryPoint + ").getObject( " + factHandle + " );";
+    }
+
+}
diff --git a/drools-core/src/main/java/org/drools/command/runtime/rule/GetObjectsInEntryPointCommand.java b/drools-core/src/main/java/org/drools/command/runtime/rule/GetObjectsInEntryPointCommand.java
new file mode 100644
index 0000000..0614411
--- /dev/null
+++ b/drools-core/src/main/java/org/drools/command/runtime/rule/GetObjectsInEntryPointCommand.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2010 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.command.runtime.rule;
+
+import org.drools.command.Context;
+import org.drools.command.impl.GenericCommand;
+import org.drools.command.impl.KnowledgeCommandContext;
+import org.drools.impl.StatefulKnowledgeSessionImpl;
+import org.drools.impl.StatefulKnowledgeSessionImpl.ObjectStoreWrapper;
+import org.drools.reteoo.ReteooWorkingMemory;
+import org.drools.runtime.ObjectFilter;
+import org.drools.runtime.StatefulKnowledgeSession;
+import org.drools.runtime.rule.WorkingMemoryEntryPoint;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+@XmlAccessorType(XmlAccessType.NONE)
+public class GetObjectsInEntryPointCommand
+    implements
+    GenericCommand<Collection> {
+
+    @XmlAttribute(name="entry-point")
+    private String entryPoint;
+
+    public String getOutIdentifier() {
+        return outIdentifier;
+    }
+
+    public void setOutIdentifier(String outIdentifier) {
+        this.outIdentifier = outIdentifier;
+    }
+
+    private ObjectFilter filter = null;
+
+    @XmlAttribute(name="out-identifier")
+    private String outIdentifier;
+
+    public GetObjectsInEntryPointCommand() {
+    }
+
+    public GetObjectsInEntryPointCommand(ObjectFilter filter, String entryPoint) {
+        this.filter = filter;
+        this.entryPoint = entryPoint;
+    }
+
+    public GetObjectsInEntryPointCommand(ObjectFilter filter, String entryPoint, String outIdentifier) {
+        this.filter = filter;
+        this.entryPoint = entryPoint;
+        this.outIdentifier = outIdentifier;
+    }
+
+    public Collection execute(Context context) {
+        StatefulKnowledgeSession ksession = ((KnowledgeCommandContext) context).getStatefulKnowledgesession();
+        WorkingMemoryEntryPoint ep = ksession.getWorkingMemoryEntryPoint(entryPoint);
+
+        Collection col = null;
+
+        if ( filter != null ) {
+
+            col =  ep.getObjects( this.filter );
+        } else {
+            col =  ep.getObjects( );
+        }
+
+        if ( this.outIdentifier != null ) {
+            List objects = new ArrayList( col );
+
+            ((StatefulKnowledgeSessionImpl)ksession).session.getExecutionResult().getResults().put( this.outIdentifier, objects );
+        }
+
+        return col;
+    }
+
+    public Collection< ? extends Object > getObjects(ReteooWorkingMemory session) {
+        return new ObjectStoreWrapper( session.getObjectStore(),
+                                       null,
+                                       ObjectStoreWrapper.OBJECT );
+    }
+
+    public Collection< ? extends Object > getObjects(ReteooWorkingMemory session, ObjectFilter filter) {
+        return new ObjectStoreWrapper( session.getObjectStore(),
+                                       filter,
+                                       ObjectStoreWrapper.OBJECT );
+    }
+
+    public String toString() {
+        if ( filter != null ) {
+            return "session.getWorkingMemoryEntryPoint(" + entryPoint + ").iterateObjects( " + filter + " );";
+        } else {
+            return "session.getWorkingMemoryEntryPoint(" + entryPoint + ").iterateObjects();";
+        }
+    }
+
+}
diff --git a/drools-core/src/main/java/org/drools/command/runtime/rule/GetWorkingMemoryEntryPointCommand.java b/drools-core/src/main/java/org/drools/command/runtime/rule/GetWorkingMemoryEntryPointCommand.java
index a3e8f46..732a8d6 100644
--- a/drools-core/src/main/java/org/drools/command/runtime/rule/GetWorkingMemoryEntryPointCommand.java
+++ b/drools-core/src/main/java/org/drools/command/runtime/rule/GetWorkingMemoryEntryPointCommand.java
@@ -17,6 +17,7 @@
 package org.drools.command.runtime.rule;
 
 import org.drools.command.Context;
+import org.drools.command.WorkingMemoryEntryPointBuilder;
 import org.drools.command.impl.GenericCommand;
 import org.drools.command.impl.KnowledgeCommandContext;
 import org.drools.runtime.StatefulKnowledgeSession;
@@ -34,7 +35,13 @@
 
     public WorkingMemoryEntryPoint execute(Context context) {
         StatefulKnowledgeSession ksession = ((KnowledgeCommandContext) context).getStatefulKnowledgesession();
-        return ksession.getWorkingMemoryEntryPoint( name );
+        WorkingMemoryEntryPoint ep = ksession.getWorkingMemoryEntryPoint(name);
+        if (ep == null) {
+            return null;
+        }
+
+        WorkingMemoryEntryPointBuilder epBuilder = (WorkingMemoryEntryPointBuilder)context.get(WorkingMemoryEntryPointBuilder.class.getName());
+        return epBuilder != null ? epBuilder.getWorkingMemoryEntryPoint(name) : ep;
     }
 
     public String toString() {
diff --git a/drools-core/src/main/java/org/drools/command/runtime/rule/GetWorkingMemoryEntryPointsCommand.java b/drools-core/src/main/java/org/drools/command/runtime/rule/GetWorkingMemoryEntryPointsCommand.java
index 7190c1c..6f4ff39 100644
--- a/drools-core/src/main/java/org/drools/command/runtime/rule/GetWorkingMemoryEntryPointsCommand.java
+++ b/drools-core/src/main/java/org/drools/command/runtime/rule/GetWorkingMemoryEntryPointsCommand.java
@@ -16,9 +16,11 @@
 
 package org.drools.command.runtime.rule;
 
+import java.util.ArrayList;
 import java.util.Collection;
 
 import org.drools.command.Context;
+import org.drools.command.WorkingMemoryEntryPointBuilder;
 import org.drools.command.impl.GenericCommand;
 import org.drools.command.impl.KnowledgeCommandContext;
 import org.drools.runtime.StatefulKnowledgeSession;
@@ -33,7 +35,16 @@
 
     public Collection< ? extends WorkingMemoryEntryPoint> execute(Context context) {
         StatefulKnowledgeSession ksession = ((KnowledgeCommandContext) context).getStatefulKnowledgesession();
-        return ksession.getWorkingMemoryEntryPoints();
+        Collection< ? extends WorkingMemoryEntryPoint> eps = ksession.getWorkingMemoryEntryPoints();
+        WorkingMemoryEntryPointBuilder epBuilder = (WorkingMemoryEntryPointBuilder)context.get(WorkingMemoryEntryPointBuilder.class.getName());
+        if (epBuilder == null) {
+            return eps;
+        }
+        Collection<WorkingMemoryEntryPoint> result = new ArrayList<WorkingMemoryEntryPoint>();
+        for (WorkingMemoryEntryPoint ep : eps) {
+            result.add(epBuilder.getWorkingMemoryEntryPoint(ep.getEntryPointId()));
+        }
+        return result;
     }
 
     public String toString() {
diff --git a/drools-core/src/main/java/org/drools/command/runtime/rule/InsertObjectInEntryPointCommand.java b/drools-core/src/main/java/org/drools/command/runtime/rule/InsertObjectInEntryPointCommand.java
index 8c4ce85..8391cb1 100644
--- a/drools-core/src/main/java/org/drools/command/runtime/rule/InsertObjectInEntryPointCommand.java
+++ b/drools-core/src/main/java/org/drools/command/runtime/rule/InsertObjectInEntryPointCommand.java
@@ -26,6 +26,7 @@
 import org.drools.command.impl.GenericCommand;
 import org.drools.command.impl.KnowledgeCommandContext;
 import org.drools.common.DefaultFactHandle;
+import org.drools.runtime.StatefulKnowledgeSession;
 import org.drools.runtime.impl.ExecutionResultImpl;
 import org.drools.runtime.rule.FactHandle;
 import org.drools.runtime.rule.WorkingMemoryEntryPoint;
@@ -42,14 +43,18 @@
     private String outIdentifier;
     private boolean returnObject = true;
 
+    @XmlAttribute(name="entry-point")
+    private String entryPoint;
+
     public InsertObjectInEntryPointCommand() {
     }
 
-    public InsertObjectInEntryPointCommand(Object object) {
+    public InsertObjectInEntryPointCommand(Object object, String entryPoint) {
         this.object = object;
+        this.entryPoint = entryPoint;
     }
 
-    public InsertObjectInEntryPointCommand(Object object, String outIdentifier) {
+    public InsertObjectInEntryPointCommand(Object object, String entryPoint, String outIdentifier) {
         super();
         this.object = object;
         this.outIdentifier = outIdentifier;
@@ -57,7 +62,8 @@
 
     public FactHandle execute(Context context) {
 
-        WorkingMemoryEntryPoint ep = ((KnowledgeCommandContext) context).getWorkingMemoryEntryPoint();
+        StatefulKnowledgeSession ksession = ((KnowledgeCommandContext) context).getStatefulKnowledgesession();
+        WorkingMemoryEntryPoint ep = ksession.getWorkingMemoryEntryPoint(entryPoint);
         FactHandle factHandle = ep.insert(object);
 
         DefaultFactHandle disconnectedHandle = ((DefaultFactHandle) factHandle).clone();
@@ -100,6 +106,6 @@
     }
 
     public String toString() {
-        return "session.insert(" + object + ");";
+        return "session.getWorkingMemoryEntryPoint(" + entryPoint + ").insert(" + object + ");";
     }
 }
diff --git a/drools-core/src/main/java/org/drools/command/runtime/rule/RetractFromEntryPointCommand.java b/drools-core/src/main/java/org/drools/command/runtime/rule/RetractFromEntryPointCommand.java
new file mode 100644
index 0000000..04fe4de
--- /dev/null
+++ b/drools-core/src/main/java/org/drools/command/runtime/rule/RetractFromEntryPointCommand.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2010 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.command.runtime.rule;
+
+import org.drools.command.Context;
+import org.drools.command.impl.GenericCommand;
+import org.drools.command.impl.KnowledgeCommandContext;
+import org.drools.common.DisconnectedFactHandle;
+import org.drools.runtime.StatefulKnowledgeSession;
+import org.drools.runtime.rule.FactHandle;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+
+@XmlAccessorType(XmlAccessType.NONE)
+public class RetractFromEntryPointCommand
+implements
+GenericCommand<Object> {
+
+    @XmlAttribute(name="entry-point")
+    private String entryPoint;
+
+    private DisconnectedFactHandle handle;
+
+    public RetractFromEntryPointCommand() {
+    }
+
+    public RetractFromEntryPointCommand(FactHandle handle, String entryPoint) {
+        this.handle = DisconnectedFactHandle.newFrom( handle );
+        this.entryPoint = entryPoint;
+    }
+
+    public Object execute(Context context) {
+        StatefulKnowledgeSession ksession = ((KnowledgeCommandContext) context).getStatefulKnowledgesession();
+        ksession.getWorkingMemoryEntryPoint( entryPoint ).retract( handle );
+        return null;
+    }
+
+    public FactHandle getFactHandle() {
+        return this.handle;
+    }
+
+    @XmlAttribute(name="fact-handle", required=true)
+    public void setFactHandleFromString(String factHandleId) {
+        handle = new DisconnectedFactHandle(factHandleId);
+    }
+
+    public String getFactHandleFromString() {
+        return handle.toExternalForm();
+    }
+
+    public String toString() {
+        return "session.getWorkingMemoryEntryPoint(" + entryPoint + ").retract( " + handle + " );";
+    }
+}
diff --git a/drools-core/src/main/java/org/drools/command/runtime/rule/UpdateInEntryPointCommand.java b/drools-core/src/main/java/org/drools/command/runtime/rule/UpdateInEntryPointCommand.java
new file mode 100644
index 0000000..9b17cf6
--- /dev/null
+++ b/drools-core/src/main/java/org/drools/command/runtime/rule/UpdateInEntryPointCommand.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2010 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.command.runtime.rule;
+
+import org.drools.command.Context;
+import org.drools.command.impl.GenericCommand;
+import org.drools.command.impl.KnowledgeCommandContext;
+import org.drools.common.DisconnectedFactHandle;
+import org.drools.runtime.StatefulKnowledgeSession;
+import org.drools.runtime.rule.FactHandle;
+
+public class UpdateInEntryPointCommand
+    implements
+    GenericCommand<Object> {
+
+    private static final long serialVersionUID = 3255044102543531497L;
+
+    private DisconnectedFactHandle handle;
+    private Object     object;
+    private String     entryPoint;
+
+    public UpdateInEntryPointCommand(FactHandle handle,
+                                     Object object,
+                                     String entryPoint) {
+        this.handle = DisconnectedFactHandle.newFrom( handle );
+        this.object = object;
+        this.entryPoint = entryPoint;
+    }
+
+    public Object execute(Context context) {
+        StatefulKnowledgeSession ksession = ((KnowledgeCommandContext) context).getStatefulKnowledgesession();
+        
+        ksession.getWorkingMemoryEntryPoint( entryPoint ).update( handle, object );
+        return null;
+    }
+    
+    public String getEntryPoint() {
+        return entryPoint;
+    }
+
+    public void setEntryPoint(String entryPoint) {
+        this.entryPoint = entryPoint;
+    }
+
+    public String toString() {
+        return "session.getWorkingMemoryEntryPoint(" + entryPoint + ").update( " + handle + ", " + object + " );";
+    }
+}
diff --git a/drools-core/src/main/java/org/drools/marshalling/impl/ProtobufOutputMarshaller.java b/drools-core/src/main/java/org/drools/marshalling/impl/ProtobufOutputMarshaller.java
index 0900e0b..26c17b9 100644
--- a/drools-core/src/main/java/org/drools/marshalling/impl/ProtobufOutputMarshaller.java
+++ b/drools-core/src/main/java/org/drools/marshalling/impl/ProtobufOutputMarshaller.java
@@ -781,5 +781,4 @@
         }
         throw new RuntimeException("Unable to serialize Trigger for type: " + trigger.getClass());
     }
-
 }
diff --git a/drools-persistence-jpa/src/main/java/org/drools/persistence/SingleSessionCommandService.java b/drools-persistence-jpa/src/main/java/org/drools/persistence/SingleSessionCommandService.java
index 6f27999..4ff6942 100644
--- a/drools-persistence-jpa/src/main/java/org/drools/persistence/SingleSessionCommandService.java
+++ b/drools-persistence-jpa/src/main/java/org/drools/persistence/SingleSessionCommandService.java
@@ -29,6 +29,7 @@
 import org.drools.command.CommandService;
 import org.drools.command.Context;
 import org.drools.command.Interceptor;
+import org.drools.command.impl.ContextImpl;
 import org.drools.command.impl.DefaultCommandService;
 import org.drools.command.impl.FixedKnowledgeCommandContext;
 import org.drools.command.impl.GenericCommand;
@@ -120,7 +121,7 @@
         this.ksession = kbase.newStatefulKnowledgeSession( conf,
                                                            this.env );
 
-        this.kContext = new FixedKnowledgeCommandContext( null,
+        this.kContext = new FixedKnowledgeCommandContext( new ContextImpl( "ksession", null),
                                                           null,
                                                           null,
                                                           this.ksession,
@@ -260,7 +261,7 @@
 
         if ( this.kContext == null ) {
             // this should only happen when this class is first constructed
-            this.kContext = new FixedKnowledgeCommandContext( null,
+            this.kContext = new FixedKnowledgeCommandContext( new ContextImpl( "ksession", null),
                                                               null,
                                                               null,
                                                               this.ksession,
diff --git a/drools-persistence-jpa/src/main/java/org/drools/persistence/jpa/KnowledgeStoreServiceImpl.java b/drools-persistence-jpa/src/main/java/org/drools/persistence/jpa/KnowledgeStoreServiceImpl.java
index ccf4c7e..c84497c 100644
--- a/drools-persistence-jpa/src/main/java/org/drools/persistence/jpa/KnowledgeStoreServiceImpl.java
+++ b/drools-persistence-jpa/src/main/java/org/drools/persistence/jpa/KnowledgeStoreServiceImpl.java
@@ -22,7 +22,9 @@
 import org.drools.KnowledgeBase;
 import org.drools.SessionConfiguration;
 import org.drools.command.CommandService;
+import org.drools.command.WorkingMemoryEntryPointBuilder;
 import org.drools.command.impl.CommandBasedStatefulKnowledgeSession;
+import org.drools.command.impl.CommandBasedWorkingMemoryEntryPoint;
 import org.drools.persistence.SingleSessionCommandService;
 import org.drools.persistence.jpa.processinstance.JPAWorkItemManagerFactory;
 import org.drools.process.instance.WorkItemManagerFactory;
@@ -31,6 +33,7 @@
 import org.drools.runtime.KnowledgeSessionConfiguration;
 import org.drools.runtime.StatefulKnowledgeSession;
 import org.drools.runtime.conf.TimerJobFactoryOption;
+import org.drools.runtime.rule.WorkingMemoryEntryPoint;
 
 public class KnowledgeStoreServiceImpl
     implements
@@ -49,7 +52,7 @@
         setCommandServiceClass( SingleSessionCommandService.class );
         setProcessInstanceManagerFactoryClass( "org.jbpm.persistence.processinstance.JPAProcessInstanceManagerFactory" );
         setWorkItemManagerFactoryClass( JPAWorkItemManagerFactory.class );
-        setProcessSignalManagerFactoryClass( "org.jbpm.persistence.processinstance.JPASignalManagerFactory" );
+        setProcessSignalManagerFactoryClass("org.jbpm.persistence.processinstance.JPASignalManagerFactory");
     }
 
     public StatefulKnowledgeSession newStatefulKnowledgeSession(KnowledgeBase kbase,
@@ -63,9 +66,12 @@
             throw new IllegalArgumentException( "Environment cannot be null" );
         }
 
-        return new CommandBasedStatefulKnowledgeSession( (CommandService) buildCommandService( kbase,
-                                                                             mergeConfig( configuration ),
-                                                                             environment ) );
+        CommandService commandService = (CommandService) buildCommandService( kbase,
+                                                                              mergeConfig( configuration ),
+                                                                              environment );
+        commandService.getContext().set(WorkingMemoryEntryPointBuilder.class.getName(),
+                                        new CommandBasedWorkingMemoryEntryPointBuilder(commandService));
+        return new CommandBasedStatefulKnowledgeSession( commandService );
     }
 
     public StatefulKnowledgeSession loadStatefulKnowledgeSession(int id,
@@ -80,10 +86,25 @@
             throw new IllegalArgumentException( "Environment cannot be null" );
         }
 
-        return new CommandBasedStatefulKnowledgeSession( (CommandService) buildCommandService( id,
-                                                                                              kbase,
-                                                                                              mergeConfig( configuration ),
-                                                                                              environment ) );
+        CommandService commandService = (CommandService) buildCommandService( id,
+                                                                              kbase,
+                                                                              mergeConfig( configuration ),
+                                                                              environment );
+        commandService.getContext().set(WorkingMemoryEntryPointBuilder.class.getName(),
+                                        new CommandBasedWorkingMemoryEntryPointBuilder(commandService));
+        return new CommandBasedStatefulKnowledgeSession( commandService );
+    }
+
+    public static class CommandBasedWorkingMemoryEntryPointBuilder implements WorkingMemoryEntryPointBuilder {
+        private final CommandService commandService;
+
+        public CommandBasedWorkingMemoryEntryPointBuilder(CommandService commandService) {
+            this.commandService = commandService;
+        }
+
+        public WorkingMemoryEntryPoint getWorkingMemoryEntryPoint(String entryPoint) {
+            return new CommandBasedWorkingMemoryEntryPoint( commandService, entryPoint );
+        }
     }
 
     private CommandExecutor buildCommandService(Integer sessionId,
diff --git a/drools-persistence-jpa/src/test/java/org/drools/persistence/session/JpaPersistentStatefulSessionTest.java b/drools-persistence-jpa/src/test/java/org/drools/persistence/session/JpaPersistentStatefulSessionTest.java
index 8b5f6b8..d26c51b 100644
--- a/drools-persistence-jpa/src/test/java/org/drools/persistence/session/JpaPersistentStatefulSessionTest.java
+++ b/drools-persistence-jpa/src/test/java/org/drools/persistence/session/JpaPersistentStatefulSessionTest.java
@@ -20,19 +20,28 @@
 import static org.junit.Assert.*;
 
 
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 
 import java.util.Properties;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CompletionService;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorCompletionService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import javax.naming.InitialContext;
 import javax.transaction.UserTransaction;
 
 import org.drools.Address;
+import org.drools.ClockType;
 import org.drools.KnowledgeBase;
+import org.drools.KnowledgeBaseConfiguration;
 import org.drools.KnowledgeBaseFactory;
 import org.drools.Person;
 import org.drools.SessionConfiguration;
@@ -43,6 +52,7 @@
 import org.drools.command.impl.CommandBasedStatefulKnowledgeSession;
 import org.drools.command.impl.FireAllRulesInterceptor;
 import org.drools.command.impl.LoggingInterceptor;
+import org.drools.conf.EventProcessingOption;
 import org.drools.io.ResourceFactory;
 import org.drools.persistence.SingleSessionCommandService;
 import org.drools.persistence.jpa.JPAKnowledgeService;
@@ -50,7 +60,9 @@
 import org.drools.runtime.Environment;
 import org.drools.runtime.KnowledgeSessionConfiguration;
 import org.drools.runtime.StatefulKnowledgeSession;
+import org.drools.runtime.conf.ClockTypeOption;
 import org.drools.runtime.rule.FactHandle;
+import org.drools.runtime.rule.WorkingMemoryEntryPoint;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -439,4 +451,179 @@
         // Should not fail here
         ksession = JPAKnowledgeService.loadStatefulKnowledgeSession(sessionId, kbase, null, env);
     }
+
+    @Test
+    public void testParallelInsertsOnPersistedSession() {
+        String str =
+                "import org.drools.persistence.session.JpaPersistentStatefulSessionTest.ParkingEvent;\n" +
+                "\n" +
+                "declare ParkingEvent\n" +
+                "    @role( event )\n" +
+                "    @expires(1s)\n" +
+                "end\n" +
+                "\n" +
+                "rule \"Hello Event\"\n" +
+                "    when\n" +
+                "        $p : ParkingEvent( ) from entry-point \"parking\"\n" +
+                "    then\n" +
+                //"        System.out.println( $p.toString() );\n" +
+                "end\n";
+
+        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
+        kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ),
+                      ResourceType.DRL );
+        KnowledgeBaseConfiguration conf = KnowledgeBaseFactory.newKnowledgeBaseConfiguration();
+        conf.setOption(EventProcessingOption.STREAM);
+        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(conf);
+
+        if ( kbuilder.hasErrors() ) {
+            fail( kbuilder.getErrors().toString() );
+        }
+
+        kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
+
+        KnowledgeSessionConfiguration ksconf = KnowledgeBaseFactory.newKnowledgeSessionConfiguration();
+        ksconf.setOption(ClockTypeOption.get(ClockType.REALTIME_CLOCK.getId()));
+        StatefulKnowledgeSession ksession = JPAKnowledgeService.newStatefulKnowledgeSession( kbase, ksconf, env );
+
+        assertNull(ksession.getWorkingMemoryEntryPoint("notExisting"));
+
+        WorkingMemoryEntryPoint ep = ksession.getWorkingMemoryEntryPoint("parking");
+
+        Executor executor = Executors.newCachedThreadPool(new ThreadFactory() {
+            public Thread newThread(Runnable r) {
+                Thread t = new Thread(r);
+                t.setDaemon(true);
+                return t;
+            }
+        });
+
+        final int THREAD_NR = 30;
+        CompletionService<Boolean> ecs = new ExecutorCompletionService<Boolean>(executor);
+        for (int i = 0; i < THREAD_NR; i++) {
+            TestEventRunner runner = new TestEventRunner();
+            runner.setEp(ep);
+            runner.setKsession(ksession);
+            ecs.submit(runner);
+        }
+
+        ksession.fireUntilHalt();
+
+        boolean success = true;
+        for (int i = 0; i < THREAD_NR; i++) {
+            try {
+                success = ecs.take().get() && success;
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        assertTrue(success);
+
+        // let to execute expirations
+        try {
+            Thread.sleep(10000L);
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        }
+
+        assertEquals(0, ep.getFactCount());
+
+        ksession.halt();
+        ksession.dispose();
+    }
+
+    public static class TestEventRunner implements Callable<Boolean> {
+
+        private WorkingMemoryEntryPoint ep;
+
+        private StatefulKnowledgeSession ksession;
+
+        public StatefulKnowledgeSession getKsession() {
+            return ksession;
+        }
+
+        public void setKsession(StatefulKnowledgeSession ksession) {
+            this.ksession = ksession;
+        }
+
+        public WorkingMemoryEntryPoint getEp() {
+            return ep;
+        }
+
+        public void setEp(WorkingMemoryEntryPoint ep) {
+            this.ep = ep;
+        }
+
+        public Boolean call() {
+            try {
+                Thread.sleep(500); // make sure ksession started
+                for (int i = 0; i < 5; i++) {
+                    ep.insert(new ParkingEvent("CarA", "ParkingA", ParkingEvent.ENTER));
+                    Thread.sleep(200);
+                    ep.insert(new ParkingEvent("CarB", "ParkingA", ParkingEvent.ENTER));
+                    Thread.sleep(200);
+                    ep.insert(new ParkingEvent("CarA", "ParkingA", ParkingEvent.EXIT));
+                    Thread.sleep(200);
+                    ep.insert(new ParkingEvent("CarA", "ParkingB", ParkingEvent.ENTER));
+                    Thread.sleep(200);
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+                return false;
+            }
+            return true;
+        }
+    }
+
+    public static class ParkingEvent implements Serializable {
+
+        public static final int ENTER = 0;
+        public static final int EXIT = 1;
+
+        private String car;
+
+        private String zone;
+
+        private int type;
+
+        public ParkingEvent() {
+
+        }
+
+        public ParkingEvent(String car, String zone, int type) {
+            this.car = car;
+            this.zone = zone;
+            this.type = type;
+        }
+
+        public String getCar() {
+            return car;
+        }
+
+        public void setCar(String car) {
+            this.car = car;
+        }
+
+        public String getZone() {
+            return zone;
+        }
+
+        public void setZone(String zone) {
+            this.zone = zone;
+        }
+
+        public int getType() {
+            return type;
+        }
+
+        public void setType(int type) {
+            this.type = type;
+        }
+
+        @Override
+        public String toString() {
+            return "ParkingEvent : car = " + car + ", zone = " + zone + ", type = " + type;
+        }
+    }
 }