From 46f1863f057fd2284df24e99efc227d2b8e5efba Mon Sep 17 00:00:00 2001 From: willemc Date: Mon, 21 Apr 2008 01:48:21 +0200 Subject: [PATCH] [svn r329] WIP commit, added EE JCA support and updated for x4o and made speed improvement and job que per process. --- .classpath | 3 + build/build-jca.xml | 121 +++++++++ build/build.properties | 16 ++ doc/todo.txt | 4 +- lib/idcanet-x4o-bin.jar | Bin 88804 -> 93189 bytes meta/jboss/foei-ds.xml | 38 +++ meta/jboss/ra.xml | 78 ++++++ .../components/lang/DestroyFoeiProcess.java | 5 + src/com/idcanet/foei/core/EventExecutor.java | 11 +- .../idcanet/foei/core/FoeiConfigurator.java | 3 - src/com/idcanet/foei/core/FoeiContext.java | 6 - .../idcanet/foei/core/FoeiPortMessage.java | 85 +++++++ src/com/idcanet/foei/core/FoeiProcess.java | 11 + .../foei/core/impl/EventExecutorImpl.java | 103 +++++--- .../core/impl/EventExecutorManagerImpl.java | 28 ++- .../foei/core/impl/FoeiConfiguratorImpl.java | 18 +- .../foei/core/impl/FoeiContextImpl.java | 20 +- .../impl/FoeiEventBindingRuleHandler.java | 3 +- .../foei/core/impl/FoeiProcessImpl.java | 19 ++ .../core/x4o/EventStepBindRuleHandler.java | 3 +- .../foei/ee/jca/cci/FoeiConnection.java | 49 ++++ .../ee/jca/cci/FoeiConnectionFactory.java | 45 ++++ .../ee/jca/cci/FoeiConnectionFactoryImpl.java | 88 +++++++ .../foei/ee/jca/cci/FoeiConnectionImpl.java | 84 +++++++ .../ee/jca/cci/FoeiManagedConnection.java | 235 ++++++++++++++++++ .../jca/cci/FoeiManagedConnectionFactory.java | 200 +++++++++++++++ .../cci/FoeiManagedConnectionMetaData.java | 70 ++++++ .../foei/ee/jca/spi/FoeiActivationSpec.java | 92 +++++++ .../foei/ee/jca/spi/FoeiEventWrapper.java | 63 +++++ .../foei/ee/jca/spi/FoeiResourceAdapter.java | 123 +++++++++ .../ee/jca/spi/JCAEventExecutorManager.java | 200 +++++++++++++++ .../foei/server/FoeiContextManager.java | 4 +- .../server/FoeiContextManagerFactory.java | 4 +- .../server/startup/FoeiStartupListener.java | 3 - tests/com/idcanet/foei/SimpleFoeiTests.java | 4 +- 35 files changed, 1734 insertions(+), 105 deletions(-) create mode 100644 build/build-jca.xml create mode 100644 build/build.properties create mode 100644 meta/jboss/foei-ds.xml create mode 100644 meta/jboss/ra.xml create mode 100644 src/com/idcanet/foei/core/FoeiPortMessage.java create mode 100644 src/com/idcanet/foei/ee/jca/cci/FoeiConnection.java create mode 100644 src/com/idcanet/foei/ee/jca/cci/FoeiConnectionFactory.java create mode 100644 src/com/idcanet/foei/ee/jca/cci/FoeiConnectionFactoryImpl.java create mode 100644 src/com/idcanet/foei/ee/jca/cci/FoeiConnectionImpl.java create mode 100644 src/com/idcanet/foei/ee/jca/cci/FoeiManagedConnection.java create mode 100644 src/com/idcanet/foei/ee/jca/cci/FoeiManagedConnectionFactory.java create mode 100644 src/com/idcanet/foei/ee/jca/cci/FoeiManagedConnectionMetaData.java create mode 100644 src/com/idcanet/foei/ee/jca/spi/FoeiActivationSpec.java create mode 100644 src/com/idcanet/foei/ee/jca/spi/FoeiEventWrapper.java create mode 100644 src/com/idcanet/foei/ee/jca/spi/FoeiResourceAdapter.java create mode 100644 src/com/idcanet/foei/ee/jca/spi/JCAEventExecutorManager.java diff --git a/.classpath b/.classpath index e934150..15875b2 100644 --- a/.classpath +++ b/.classpath @@ -9,5 +9,8 @@ + + + diff --git a/build/build-jca.xml b/build/build-jca.xml new file mode 100644 index 0000000..bf62916 --- /dev/null +++ b/build/build-jca.xml @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/build.properties b/build/build.properties new file mode 100644 index 0000000..98eb309 --- /dev/null +++ b/build/build.properties @@ -0,0 +1,16 @@ + +# Name of the server to build the application for: +server.name = jboss + +# Home directory of JBoss 4.0.2 J2ee Application Server and name of the server +# instance on which the application should be deployed (this instance should be +# either a copy of the default JBoss server or the default server itself because +# its libs are also used for building the source code): +jboss.home = /home/willemc/devv/jboss-4.2.1.GA +jboss.server = default + +# Home directory of Geronimo 1.0M5 J2ee Application Server and its administrator +# credentials: +geronimo.home = /home/willemc/devv/apache-geronimo +geronimo.user = system +geronimo.password = manager diff --git a/doc/todo.txt b/doc/todo.txt index a1cd25a..457a1c9 100644 --- a/doc/todo.txt +++ b/doc/todo.txt @@ -1,7 +1,7 @@ --- IDCANET X4O TODO list -- +-- IDCANET FOEI TODO list -- -- make J2EE compaitle +- (80% DONE) make J2EE compaitle - Add annotations for ports - Make asysc piping faster - Start implementing JMS interfaces diff --git a/lib/idcanet-x4o-bin.jar b/lib/idcanet-x4o-bin.jar index 5a7c348e45a194af16bf3a5f59cc0a5994071b65..d87fffd7825e4d5be3be2416017dcc60bea022cf 100644 GIT binary patch delta 46184 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 S3BnTudpZP!Fa@x95dH_#$Toif delta 42149 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 F{{ZrL@n8S| diff --git a/meta/jboss/foei-ds.xml b/meta/jboss/foei-ds.xml new file mode 100644 index 0000000..89d602d --- /dev/null +++ b/meta/jboss/foei-ds.xml @@ -0,0 +1,38 @@ + + + + + + + + + foei/datafeeds + foei-ra.rar + com.idcanet.foei.ee.jca.cci.FoeiConnectionFactory + datafeeds + + 2 + 200 + 32123 + 1 + + + + + foei/m4n + foei-ra.rar + com.idcanet.foei.ee.jca.cci.FoeiConnectionFactory + m4n + + + 2 + 200 + 32888 + 1 + + + + diff --git a/meta/jboss/ra.xml b/meta/jboss/ra.xml new file mode 100644 index 0000000..5b36428 --- /dev/null +++ b/meta/jboss/ra.xml @@ -0,0 +1,78 @@ + + + + + FoeiJCA + IDCA + Foei Adapter + 1.0 + + +Copyright 2004-2006 IDCA. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and + the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions + and the following disclaimer in the documentation and/or other materials provided with the + distribution. + +THIS SOFTWARE IS PROVIDED BY IDCA AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IDCA OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those of the authors and +should not be interpreted as representing official policies, either expressed or implied, of IDCA. + + true + + + + com.idcanet.foei.ee.jca.spi.FoeiResourceAdapter + + + + com.idcanet.foei.ee.jca.cci.FoeiManagedConnectionFactory + + The foei context name. + foeiContextName + java.lang.String + + com.idcanet.foei.ee.jca.cci.FoeiConnectionFactory + com.idcanet.foei.ee.jca.cci.FoeiConnectionFactoryImpl + com.idcanet.foei.ee.jca.cci.FoeiConnection + com.idcanet.foei.ee.jca.cci.FoeiConnectionImpl + + NoTransaction + false + + + + + + com.idcanet.foei.event.EventInput + + com.idcanet.foei.ee.jca.spi.FoeiActivationSpec + + beanName + + + + + + + + + diff --git a/src/com/idcanet/foei/components/lang/DestroyFoeiProcess.java b/src/com/idcanet/foei/components/lang/DestroyFoeiProcess.java index 0ed13a4..2d52428 100644 --- a/src/com/idcanet/foei/components/lang/DestroyFoeiProcess.java +++ b/src/com/idcanet/foei/components/lang/DestroyFoeiProcess.java @@ -80,6 +80,11 @@ public class DestroyFoeiProcess extends AbstractEventInput { throw new IllegalEventPortNameException("Not excisting input EventPort: "+eventPort.getName()); } FoeiProcess process = FoeiProcessFactory.getFoeiProcess(); + + if (process.getWorkQueue().isEmpty()==false) { + //return; + } + if(delayTime!=null) { try { logger.info("Sleeping "+delayTime+" ms before destoying process: "+process.getName()); diff --git a/src/com/idcanet/foei/core/EventExecutor.java b/src/com/idcanet/foei/core/EventExecutor.java index 4a54b89..9aa672a 100644 --- a/src/com/idcanet/foei/core/EventExecutor.java +++ b/src/com/idcanet/foei/core/EventExecutor.java @@ -26,8 +26,6 @@ package com.idcanet.foei.core; -import com.idcanet.foei.event.EventPort; - /** * Reuables EventExecutor wich are executed * in the EcentExecutorManager @@ -38,16 +36,11 @@ import com.idcanet.foei.event.EventPort; public interface EventExecutor extends Runnable { /** - * Sets the object to process. + * Sets the foei process * @param object */ - public void setEventObject(Object object); + public void setFoeiProcess(FoeiProcess foeiProcess); - /** - * Sets the eventPort to/from the object needs to go. - * @param eventPort - */ - public void setEventPort(EventPort eventPort); /** * Returns true when this EventExecutor is ready diff --git a/src/com/idcanet/foei/core/FoeiConfigurator.java b/src/com/idcanet/foei/core/FoeiConfigurator.java index 918d7c0..421aeb4 100644 --- a/src/com/idcanet/foei/core/FoeiConfigurator.java +++ b/src/com/idcanet/foei/core/FoeiConfigurator.java @@ -41,9 +41,6 @@ public interface FoeiConfigurator { /** The key of the foei fontext name */ static public final String CONTEXT_NAME = "foei.context_name"; - /** The key of the root path */ - static public final String ROOT_PATH = "foei.root_path"; - /** The key of the className of the ObjectBindingsManager */ static public final String OBJECT_BINDINGS_MANAGER = "foei.object_bindings_manager"; diff --git a/src/com/idcanet/foei/core/FoeiContext.java b/src/com/idcanet/foei/core/FoeiContext.java index 5450f17..80025a4 100644 --- a/src/com/idcanet/foei/core/FoeiContext.java +++ b/src/com/idcanet/foei/core/FoeiContext.java @@ -44,12 +44,6 @@ public interface FoeiContext { */ public String getName(); - /** - * Gets the root path. - * @return returns the root path. - */ - public String getRootPath(); - /** * Gets the EventObjectContext. * @return Returns the Context diff --git a/src/com/idcanet/foei/core/FoeiPortMessage.java b/src/com/idcanet/foei/core/FoeiPortMessage.java new file mode 100644 index 0000000..1756ccd --- /dev/null +++ b/src/com/idcanet/foei/core/FoeiPortMessage.java @@ -0,0 +1,85 @@ +/* + * Copyright 2004-2006 IDCA. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and + * the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions + * and the following disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY IDCA AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IDCA OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the authors and + * should not be interpreted as representing official policies, either expressed or implied, of IDCA. + */ + +package com.idcanet.foei.core; + +import com.idcanet.foei.event.EventPort; + +/** + * Message block used in work queue to store non-immatiate port events. + * + * @author Willem Cazander + * @version 1.0 Apr 9, 2008 + */ +public class FoeiPortMessage { + + /** The event obect. */ + private Object eventObject = null; + /** The eventport */ + private EventPort eventPort = null; + + public FoeiPortMessage() { + } + + public FoeiPortMessage(Object eventObject,EventPort eventPort) { + setEventObject(eventObject); + setEventPort(eventPort); + } + + /** + * @return the eventObject + */ + public Object getEventObject() { + return eventObject; + } + + /** + * @param eventObject the eventObject to set + */ + public void setEventObject(Object eventObject) { + if (eventObject==null) { + throw new NullPointerException("May not set null eventObject"); + } + this.eventObject = eventObject; + } + + /** + * @return the eventPort + */ + public EventPort getEventPort() { + return eventPort; + } + + /** + * @param eventPort the eventPort to set + */ + public void setEventPort(EventPort eventPort) { + if (eventPort==null) { + throw new NullPointerException("May not set null eventPort"); + } + this.eventPort = eventPort; + } +} \ No newline at end of file diff --git a/src/com/idcanet/foei/core/FoeiProcess.java b/src/com/idcanet/foei/core/FoeiProcess.java index e20c667..4c47ef5 100644 --- a/src/com/idcanet/foei/core/FoeiProcess.java +++ b/src/com/idcanet/foei/core/FoeiProcess.java @@ -26,6 +26,9 @@ package com.idcanet.foei.core; +import java.util.Queue; +import java.util.Set; + import javax.naming.Context; /** @@ -66,4 +69,12 @@ public interface FoeiProcess extends ObjectBindingsManager,ObjectContextManager, * Stops all stuff in this process */ public void destroy(); + + /** + * Returns the work queue for this foei process + * @return + */ + public Queue getWorkQueue(); + + public Set getExecutors(); } \ No newline at end of file diff --git a/src/com/idcanet/foei/core/impl/EventExecutorImpl.java b/src/com/idcanet/foei/core/impl/EventExecutorImpl.java index cb9b61b..69bc00d 100644 --- a/src/com/idcanet/foei/core/impl/EventExecutorImpl.java +++ b/src/com/idcanet/foei/core/impl/EventExecutorImpl.java @@ -27,11 +27,13 @@ package com.idcanet.foei.core.impl; import com.idcanet.foei.core.EventExecutor; +import com.idcanet.foei.core.FoeiPortMessage; import com.idcanet.foei.core.FoeiProcess; import com.idcanet.foei.core.FoeiProcessFactory; import com.idcanet.foei.event.EventInput; import com.idcanet.foei.event.EventPort; import com.idcanet.foei.event.EventPortType; +import com.idcanet.foei.event.IllegalEventPortNameException; import java.util.List; import java.util.logging.Level; @@ -48,11 +50,12 @@ public class EventExecutorImpl implements EventExecutor { /** The logger to log to. */ private Logger logger = null; /** The event obect. */ - private Object eventObject = null; + //private Object eventObject = null; /** The eventport */ - private EventPort eventPort = null; + //private EventPort eventPort = null; + private FoeiProcess foeiProcess = null; /** True when ready */ - private boolean ready = false; + private volatile boolean ready = false; /** * Creates an EventExecutor @@ -64,14 +67,16 @@ public class EventExecutorImpl implements EventExecutor { /** * @see EventExecutor#setEventObject(Object) */ - public void setEventObject(Object eventObject) { - this.eventObject=eventObject; - ready = false; + public void setFoeiProcess(FoeiProcess foeiProcess) { + this.foeiProcess=foeiProcess; + //this.eventObject=eventObject; + //ready = false; } /** * @see EventExecutor#setEventPort(EventPort) */ + /* public void setEventPort(EventPort eventPort) { if(eventPort==null) { throw new NullPointerException("EventPort may not be null."); @@ -79,6 +84,7 @@ public class EventExecutorImpl implements EventExecutor { this.eventPort=eventPort; ready = false; } + */ /** * @see EventExecutor#isReady() @@ -91,43 +97,74 @@ public class EventExecutorImpl implements EventExecutor { * @see Runnable#run() */ public void run() { - if(eventPort==null) { - logger.warning("Can't execute event on null eventPort."); + if(foeiProcess==null) { + logger.warning("Can't execute event on null foeiProcess."); return; } ready = false; + int processed = 0; try { - FoeiProcess foeiProcess = FoeiProcessFactory.getFoeiProcess(); - if(eventPort.getEventPortType()==EventPortType.input) { - EventInput eventInput = (EventInput)eventPort.getEventObject(); - eventPort.addEventsPassed(); // inc input port - eventInput.doEvent(eventPort,eventObject); - return; + //FoeiProcess foeiProcess = FoeiProcessFactory.getFoeiProcess(); + FoeiProcessFactory.bindFoeiProcess(foeiProcess); + + FoeiPortMessage msg = foeiProcess.getWorkQueue().poll(); + while (msg!=null) { + process(msg); + processed++; + msg = foeiProcess.getWorkQueue().poll(); } - if(eventPort.getEventPortType()==EventPortType.output) { - eventPort.addEventsPassed(); // inc output port - - // uses the faster routine to get bindings ..., - //List bindings = foeiProcess.getBindings(eventPort); - List bindings = foeiProcess.getBindingsInputPorts(eventPort); - - for (int i=0;i bindings = foeiProcess.getBindings(eventPort); + List bindings = foeiProcess.getBindingsInputPorts(eventPort); + + for (int i=0;i3) { + return; + } + EventExecutor e = null; try { e = (EventExecutor)eventExecutorClass.newInstance(); @@ -90,14 +101,17 @@ public class EventExecutorManagerImpl implements EventExecutorManager { logger.log(Level.WARNING,"Error Creating EventExecutor: "+ee.getMessage(),ee); return; } - e.setEventObject(eventObject); - e.setEventPort(eventPort); - if(eventPort.isImmediate()) { - e.run(); - } else { + e.setFoeiProcess(foeiProcess); + foeiProcess.getExecutors().add(e); + //e.setEventObject(eventObject); + //e.setEventPort(eventPort); + //if(eventPort.isImmediate()) { + // e.run(); + //} else { // mmmm - execute(e,foeiProcess); - } + //execute(e,foeiProcess); + threadPoolExecutor.execute(e); + //} } /** diff --git a/src/com/idcanet/foei/core/impl/FoeiConfiguratorImpl.java b/src/com/idcanet/foei/core/impl/FoeiConfiguratorImpl.java index e260c7f..5b0a194 100644 --- a/src/com/idcanet/foei/core/impl/FoeiConfiguratorImpl.java +++ b/src/com/idcanet/foei/core/impl/FoeiConfiguratorImpl.java @@ -64,13 +64,11 @@ public class FoeiConfiguratorImpl implements FoeiConfigurator { throw new NullPointerException("properties may not be null."); } String name = getContextName(properties); - String rootPath = null; Context objectContext = null; EventExecutorManager eventExecutorManager = null; FoeiProcessManager foeiProcessManager = null; try { - rootPath = getRootPath(properties); objectContext = newContext(properties); eventExecutorManager = newEventExecutorManager(properties); foeiProcessManager = newFoeiProcessManager(properties); @@ -78,7 +76,7 @@ public class FoeiConfiguratorImpl implements FoeiConfigurator { } catch (Exception e) { throw new FoeiContextBuildingException("Error while building childs objects:",e); } - return new FoeiContextImpl(name,rootPath,objectContext,eventExecutorManager,properties,foeiProcessManager); + return new FoeiContextImpl(name,objectContext,eventExecutorManager,properties,foeiProcessManager); } /** @@ -94,20 +92,6 @@ public class FoeiConfiguratorImpl implements FoeiConfigurator { return contextName; } - /** - * Gets the root path from the properties Map. - * @param properties The properties map. - * @return Returns the rootpath from the properties map. - */ - static public String getRootPath(Map properties) { - String rootPath = properties.get(FoeiConfigurator.ROOT_PATH); - if(rootPath==null) { - throw new NullPointerException("rootPath needs to be set in properties as: "+FoeiConfigurator.ROOT_PATH); - } - return rootPath; - } - - /** * * @param properties diff --git a/src/com/idcanet/foei/core/impl/FoeiContextImpl.java b/src/com/idcanet/foei/core/impl/FoeiContextImpl.java index bcb25e3..e5a5c91 100644 --- a/src/com/idcanet/foei/core/impl/FoeiContextImpl.java +++ b/src/com/idcanet/foei/core/impl/FoeiContextImpl.java @@ -40,14 +40,11 @@ import javax.naming.Context; * @author Willem Cazander * @version 1.0 Jan 19, 2006 */ -public class FoeiContextImpl implements FoeiContext -{ +public class FoeiContextImpl implements FoeiContext { + /** The name of this Instance **/ private String name = null; - /** The root path of this instance **/ - private String rootPath = null; - /** The FoeiContext where all objects are stored. **/ private Context objectContext = null; @@ -70,14 +67,11 @@ public class FoeiContextImpl implements FoeiContext * @param eventExecutorManager * @param startProperties */ - public FoeiContextImpl(String name,String rootPath,Context objectContext,EventExecutorManager eventExecutorManager,Map startProperties,FoeiProcessManager foeiProcessManager) { + public FoeiContextImpl(String name,Context objectContext,EventExecutorManager eventExecutorManager,Map startProperties,FoeiProcessManager foeiProcessManager) { if(name==null) { throw new NullPointerException("name may not be null."); } - if(rootPath==null) { - throw new NullPointerException("rootPath may not be null."); - } if(objectContext==null) { throw new NullPointerException("objectContext may not be null."); } @@ -89,7 +83,6 @@ public class FoeiContextImpl implements FoeiContext } this.name=name; - this.rootPath=rootPath; this.objectContext=objectContext; this.eventExecutorManager=eventExecutorManager; this.startProperties=startProperties; @@ -104,13 +97,6 @@ public class FoeiContextImpl implements FoeiContext return name; } - /** - * @see FoeiContext#getRootPath() - */ - public String getRootPath() { - return rootPath; - } - /** * @see FoeiContext#getEventExecutorManager() */ diff --git a/src/com/idcanet/foei/core/impl/FoeiEventBindingRuleHandler.java b/src/com/idcanet/foei/core/impl/FoeiEventBindingRuleHandler.java index 5071a26..29a8daf 100644 --- a/src/com/idcanet/foei/core/impl/FoeiEventBindingRuleHandler.java +++ b/src/com/idcanet/foei/core/impl/FoeiEventBindingRuleHandler.java @@ -7,6 +7,7 @@ import com.idcanet.foei.event.EventOutput; import com.idcanet.foei.event.EventStep; import com.idcanet.foei.event.EventStepController; import com.idcanet.x4o.element.Element; +import com.idcanet.x4o.element.ElementBindingException; import com.idcanet.x4o.element.ElementBindingHandler; /** @@ -65,7 +66,7 @@ public class FoeiEventBindingRuleHandler implements ElementBindingHandler { * @param object2 * @throws ClassCastException */ - public void doBind(Element element) throws Exception { + public void doBind(Element element) throws ElementBindingException { Object parent = element.getParent().getElementObject(); Object child = element.getElementObject(); if(parent==null) { diff --git a/src/com/idcanet/foei/core/impl/FoeiProcessImpl.java b/src/com/idcanet/foei/core/impl/FoeiProcessImpl.java index 8364510..bc6d0ba 100644 --- a/src/com/idcanet/foei/core/impl/FoeiProcessImpl.java +++ b/src/com/idcanet/foei/core/impl/FoeiProcessImpl.java @@ -26,12 +26,19 @@ package com.idcanet.foei.core.impl; +import com.idcanet.foei.core.EventExecutor; import com.idcanet.foei.core.FoeiContext; +import com.idcanet.foei.core.FoeiPortMessage; import com.idcanet.foei.core.FoeiProcess; import com.idcanet.foei.core.ObjectBindingsManager; import com.idcanet.foei.event.EventPort; +import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Queue; +import java.util.Set; +import java.util.concurrent.LinkedBlockingQueue; import java.util.logging.Level; import java.util.logging.Logger; @@ -59,6 +66,10 @@ public class FoeiProcessImpl implements FoeiProcess { /** The ObjectBindingsManager */ private ObjectBindingsManager objectBindingsManager = null; + private Queue foeiPortMessages = new LinkedBlockingQueue(); + + private Set eventExecutors = Collections.synchronizedSet(new HashSet(10)); + public FoeiProcessImpl(String name,FoeiContext foeiContext,Context eventObjectContext,ObjectBindingsManager objectBindingsManager) { logger = Logger.getLogger(FoeiProcessImpl.class.getName()); this.name=name; @@ -105,6 +116,14 @@ public class FoeiProcessImpl implements FoeiProcess { return foeiContext; } + public Queue getWorkQueue() { + return foeiPortMessages; + } + + public Set getExecutors() { + return eventExecutors; + } + // ================== EventPortExecutor /** diff --git a/src/com/idcanet/foei/core/x4o/EventStepBindRuleHandler.java b/src/com/idcanet/foei/core/x4o/EventStepBindRuleHandler.java index c982f76..8c74253 100644 --- a/src/com/idcanet/foei/core/x4o/EventStepBindRuleHandler.java +++ b/src/com/idcanet/foei/core/x4o/EventStepBindRuleHandler.java @@ -29,6 +29,7 @@ package com.idcanet.foei.core.x4o; import com.idcanet.foei.event.EventStep; import com.idcanet.foei.event.EventStepController; import com.idcanet.x4o.element.Element; +import com.idcanet.x4o.element.ElementBindingException; import com.idcanet.x4o.element.ElementBindingHandler; /** @@ -57,7 +58,7 @@ public class EventStepBindRuleHandler implements ElementBindingHandler { /** * @see com.idca.foei.xml.x2o.eld.BindingRuleHandler#doBind(java.lang.Object, java.lang.Object) */ - public void doBind(Element element) throws Exception { + public void doBind(Element element) throws ElementBindingException { Object parent = element.getParent().getElementObject(); Object child = element.getElementObject(); ((EventStepController)parent).addEventStep((EventStep)child); diff --git a/src/com/idcanet/foei/ee/jca/cci/FoeiConnection.java b/src/com/idcanet/foei/ee/jca/cci/FoeiConnection.java new file mode 100644 index 0000000..2c0a9e0 --- /dev/null +++ b/src/com/idcanet/foei/ee/jca/cci/FoeiConnection.java @@ -0,0 +1,49 @@ +/* + * Copyright 2004-2008 IDCA. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and + * the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions + * and the following disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY IDCA AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IDCA OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the authors and + * should not be interpreted as representing official policies, either expressed or implied, of IDCA. + */ + +package com.idcanet.foei.ee.jca.cci; + +import javax.resource.ResourceException; + +import com.idcanet.foei.core.FoeiContext; + +/** + * + * + * @author Willem Cazander + * @version 1.0 Apr 19, 2008 + */ +public interface FoeiConnection { + + /** + * Retrieves instance of the Foei Context + * @return File Retriever connection instance + * @throws ResourceException in case of any problem + */ + public FoeiContext getFoeiContext() throws ResourceException; + + public void close() throws ResourceException; +} diff --git a/src/com/idcanet/foei/ee/jca/cci/FoeiConnectionFactory.java b/src/com/idcanet/foei/ee/jca/cci/FoeiConnectionFactory.java new file mode 100644 index 0000000..399e3be --- /dev/null +++ b/src/com/idcanet/foei/ee/jca/cci/FoeiConnectionFactory.java @@ -0,0 +1,45 @@ +/* + * Copyright 2004-2008 IDCA. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and + * the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions + * and the following disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY IDCA AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IDCA OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the authors and + * should not be interpreted as representing official policies, either expressed or implied, of IDCA. + */ + +package com.idcanet.foei.ee.jca.cci; + +import javax.resource.ResourceException; + +/** + * + * + * @author Willem Cazander + * @version 1.0 Apr 19, 2008 + */ +public interface FoeiConnectionFactory { + + /** + * Retrieves instance of the Foei Context Connection + * @return File Retriever connection instance + * @throws ResourceException in case of any problem + */ + public FoeiConnection getFoeiConnection() throws ResourceException; +} diff --git a/src/com/idcanet/foei/ee/jca/cci/FoeiConnectionFactoryImpl.java b/src/com/idcanet/foei/ee/jca/cci/FoeiConnectionFactoryImpl.java new file mode 100644 index 0000000..665effa --- /dev/null +++ b/src/com/idcanet/foei/ee/jca/cci/FoeiConnectionFactoryImpl.java @@ -0,0 +1,88 @@ +/* + * Copyright 2004-2008 IDCA. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and + * the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions + * and the following disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY IDCA AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IDCA OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the authors and + * should not be interpreted as representing official policies, either expressed or implied, of IDCA. + */ + +package com.idcanet.foei.ee.jca.cci; + +import java.io.Serializable; + +import javax.naming.NamingException; +import javax.naming.Reference; +import javax.resource.Referenceable; +import javax.resource.ResourceException; +import javax.resource.spi.ConnectionManager; +import javax.resource.spi.ManagedConnectionFactory; + +/** + * + * + * @author Willem Cazander + * @version 1.0 Apr 19, 2008 + */ +@SuppressWarnings("serial") +public class FoeiConnectionFactoryImpl implements FoeiConnectionFactory, Serializable, Referenceable { + + /** Managed connection factory */ + private ManagedConnectionFactory mcf; + + /** Connection manager */ + private ConnectionManager cm; + + /** JNDI reference */ + private Reference reference; + + + /** + * The constructor + * @param factory managed connection factory + * @param cm connection manager + */ + public FoeiConnectionFactoryImpl(ManagedConnectionFactory factory,ConnectionManager cm) { + this.mcf = factory; + this.cm = cm; + } + + + /** + * @see javax.resource.Referenceable#setReference(javax.naming.Reference) + */ + public void setReference(Reference reference) { + this.reference=reference; + } + + /** + * @see javax.naming.Referenceable#getReference() + */ + public Reference getReference() throws NamingException { + return reference; + } + + /** + * @see com.idcanet.foei.jca.cci.FoeiConnectionFactory#getFoeiConnection() + */ + public FoeiConnection getFoeiConnection() throws ResourceException { + return (FoeiConnection) cm.allocateConnection(mcf, null); + } +} \ No newline at end of file diff --git a/src/com/idcanet/foei/ee/jca/cci/FoeiConnectionImpl.java b/src/com/idcanet/foei/ee/jca/cci/FoeiConnectionImpl.java new file mode 100644 index 0000000..31e80a5 --- /dev/null +++ b/src/com/idcanet/foei/ee/jca/cci/FoeiConnectionImpl.java @@ -0,0 +1,84 @@ +/* + * Copyright 2004-2008 IDCA. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and + * the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions + * and the following disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY IDCA AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IDCA OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the authors and + * should not be interpreted as representing official policies, either expressed or implied, of IDCA. + */ + +package com.idcanet.foei.ee.jca.cci; + +import javax.resource.ResourceException; +import com.idcanet.foei.core.FoeiContext; + +/** + * + * + * @author Willem Cazander + * @version 1.0 Apr 19, 2008 + */ +public class FoeiConnectionImpl implements FoeiConnection { + + + /** Underlying physical connection instance */ + private FoeiManagedConnection mc; + + /** + * The constructor + * @param mc underlying physical connection instance + */ + public FoeiConnectionImpl(FoeiManagedConnection mc) { + this.mc = mc; + } + + /** + * Associates this handle with given underlying physical + * connection instance + * @param newMc underlying physical connection instance + */ + public void associateConnection(FoeiManagedConnection newMc) { + this.mc.removeConnection(this); + newMc.addConnection(this); + this.mc = newMc; + } + + /** + * Invalidates the connection + */ + public void invalidate() { + mc = null; + } + + /** + * @see com.idcanet.foei.jca.cci.FoeiContextConnection#getFoeiContext() + */ + public FoeiContext getFoeiContext() throws ResourceException { + return mc.getFoeiContext(); + } + + /**oeiContextConnection#close() + */ + public void close() throws ResourceException { + mc.close(this); + } + + +} \ No newline at end of file diff --git a/src/com/idcanet/foei/ee/jca/cci/FoeiManagedConnection.java b/src/com/idcanet/foei/ee/jca/cci/FoeiManagedConnection.java new file mode 100644 index 0000000..6d36fba --- /dev/null +++ b/src/com/idcanet/foei/ee/jca/cci/FoeiManagedConnection.java @@ -0,0 +1,235 @@ +/* + * Copyright 2004-2008 IDCA. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and + * the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions + * and the following disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY IDCA AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IDCA OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the authors and + * should not be interpreted as representing official policies, either expressed or implied, of IDCA. + */ + +package com.idcanet.foei.ee.jca.cci; + +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import javax.resource.NotSupportedException; +import javax.resource.ResourceException; +import javax.resource.spi.ConnectionEvent; +import javax.resource.spi.ConnectionEventListener; +import javax.resource.spi.ConnectionRequestInfo; +import javax.resource.spi.LocalTransaction; +import javax.resource.spi.ManagedConnection; +import javax.resource.spi.ManagedConnectionMetaData; +import javax.security.auth.Subject; +import javax.transaction.xa.XAResource; + +import com.idcanet.foei.core.FoeiContext; + +/** + * + * + * @author Willem Cazander + * @version 1.0 Apr 19, 2008 + */ +public class FoeiManagedConnection implements ManagedConnection { + + /** Log writer */ + private PrintWriter writer; + + /** List of listeners */ + private List listeners; + + /** Set of application-level handlers */ + private Set connectionSet; + + private FoeiContext foeiContext = null; + + /** + * The constructor + * @param conReqInfo {@link ConnectionRequestInfo} + * @param writer log writer of the factory that calls this constructor + * @param repositoryPath path to the repository containing files to retireve + */ + public FoeiManagedConnection(ConnectionRequestInfo conReqInfo,PrintWriter writer, FoeiContext foeiContext) { + this.writer = writer; + this.listeners = new ArrayList(10); + this.connectionSet = new HashSet(10); + this.foeiContext = foeiContext; + } + + /** + * @see javax.resource.spi.ManagedConnection#getConnection(javax.security.auth.Subject, + * javax.resource.spi.ConnectionRequestInfo) + */ + public Object getConnection(Subject subj, ConnectionRequestInfo conReqInfo) throws ResourceException { + if (this.foeiContext == null) { + throw new ResourceException("foeiContext is null"); + } + + FoeiConnectionImpl conn = new FoeiConnectionImpl(this); + addConnection(conn); + return conn; + } + + /** + * @see javax.resource.spi.ManagedConnection#destroy() + */ + public void destroy() throws ResourceException { + invalidateAllConnections(); + synchronized (this.listeners) { + listeners = null; + } + foeiContext = null; + } + + /** + * @see javax.resource.spi.ManagedConnection#cleanup() + */ + public void cleanup() throws ResourceException { + invalidateAllConnections(); + } + + /** + * @see javax.resource.spi.ManagedConnection#associateConnection(java.lang.Object) + */ + public void associateConnection(Object conn) throws ResourceException { + if (!(conn instanceof FoeiConnectionImpl)) { + throw new ResourceException("Connection has an incorrect type"); + } + ((FoeiConnectionImpl)conn).associateConnection(this); + } + + /** + * @see javax.resource.spi.ManagedConnection#addConnectionEventListener(javax.resource.spi.ConnectionEventListener) + */ + public void addConnectionEventListener(ConnectionEventListener listener) { + synchronized (this.listeners) { + listeners.add(listener); + } + } + + /** + * @see javax.resource.spi.ManagedConnection#removeConnectionEventListener(javax.resource.spi.ConnectionEventListener) + */ + public void removeConnectionEventListener(ConnectionEventListener listener) { + synchronized (this.listeners) { + listeners.remove(listener); + } + } + + /** + * @see javax.resource.spi.ManagedConnection#getXAResource() + */ + public XAResource getXAResource() throws ResourceException { + throw new NotSupportedException("XA transactions are not supported"); + } + + /** + * @see javax.resource.spi.ManagedConnection#getLocalTransaction() + */ + public LocalTransaction getLocalTransaction() throws ResourceException { + throw new NotSupportedException("Transactions are not supported"); + } + + /** + * @see javax.resource.spi.ManagedConnection#getMetaData() + */ + public ManagedConnectionMetaData getMetaData() throws ResourceException { + return new FoeiManagedConnectionMetaData(); + } + + /** + * @see javax.resource.spi.ManagedConnection#setLogWriter(java.io.PrintWriter) + */ + public void setLogWriter(PrintWriter out) throws ResourceException { + this.writer = out; + } + + /** + * @see javax.resource.spi.ManagedConnection#getLogWriter() + */ + public PrintWriter getLogWriter() throws ResourceException { + return writer; + } + + /** + * Removes application-level handler from handlers set + * @param con handler to remove + * @see FileRetrieverConnectionImpl#associateConnection(FileRetrieverManagedConnection) + */ + void removeConnection(FoeiConnectionImpl con) { + synchronized (this.connectionSet) { + connectionSet.remove(con); + } + } + + /** + * Adds application-level handler to handlers set + * @param con handler to add + * @see FileRetrieverConnectionImpl#associateConnection(FileRetrieverManagedConnection) + */ + void addConnection(FoeiConnectionImpl con) { + synchronized (this.connectionSet) { + connectionSet.add(con); + } + } + + /** + * Invalidate all application-level handlers and clears handlers set + */ + void invalidateAllConnections() { + synchronized (this.connectionSet) { + Iterator itr = connectionSet.iterator(); + while (itr.hasNext()) { + FoeiConnectionImpl con = itr.next(); + con.invalidate(); + } + connectionSet.clear(); + } + } + + public FoeiContext getFoeiContext() { + return foeiContext; + } + + + /** + * Closes connection + * @param con connection to close + */ + public void close(FoeiConnectionImpl con) { + ConnectionEvent event = new ConnectionEvent(this, ConnectionEvent.CONNECTION_CLOSED); + synchronized (this.listeners) { + Iterator itr = listeners.iterator(); + while (itr.hasNext()) { + try { + itr.next().connectionClosed(event); + } catch (Throwable e) { + } + } + } + con.invalidate(); + removeConnection(con); + } +} diff --git a/src/com/idcanet/foei/ee/jca/cci/FoeiManagedConnectionFactory.java b/src/com/idcanet/foei/ee/jca/cci/FoeiManagedConnectionFactory.java new file mode 100644 index 0000000..b8b9caa --- /dev/null +++ b/src/com/idcanet/foei/ee/jca/cci/FoeiManagedConnectionFactory.java @@ -0,0 +1,200 @@ +/* + * Copyright 2004-2008 IDCA. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and + * the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions + * and the following disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY IDCA AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IDCA OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the authors and + * should not be interpreted as representing official policies, either expressed or implied, of IDCA. + */ + +package com.idcanet.foei.ee.jca.cci; + +import java.io.PrintWriter; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.logging.Logger; + +import javax.naming.Context; +import javax.resource.ResourceException; +import javax.resource.spi.ConnectionManager; +import javax.resource.spi.ConnectionRequestInfo; +import javax.resource.spi.ManagedConnection; +import javax.resource.spi.ManagedConnectionFactory; +import javax.resource.spi.ResourceAdapter; +import javax.resource.spi.ResourceAdapterAssociation; +import javax.security.auth.Subject; + +import com.idcanet.foei.core.EventExecutorManager; +import com.idcanet.foei.core.FoeiContext; +import com.idcanet.foei.core.FoeiProcessManager; +import com.idcanet.foei.core.impl.FoeiConfiguratorImpl; +import com.idcanet.foei.core.impl.FoeiContextImpl; +import com.idcanet.foei.ee.jca.spi.FoeiResourceAdapter; +import com.idcanet.foei.ee.jca.spi.JCAEventExecutorManager; + +/** + * + * + * @author Willem Cazander + * @version 1.0 Apr 19, 2008 + */ +@SuppressWarnings("serial") +public class FoeiManagedConnectionFactory implements ManagedConnectionFactory,ResourceAdapterAssociation { + + private Logger logger = Logger.getLogger(FoeiManagedConnectionFactory.class.getName()); + + /** Log writer */ + private transient PrintWriter writer; + + /** Path to file system repository */ + private String foeiContextName = null; + + private FoeiContext foeiContext = null; + + private ResourceAdapter resourceAdapter = null; + + /** + * @see javax.resource.spi.ManagedConnectionFactory#createConnectionFactory(javax.resource.spi.ConnectionManager) + */ + public Object createConnectionFactory(ConnectionManager cm) throws ResourceException { + + if (foeiContext==null) { + logger.info("Starting foeiContext: "+foeiContextName); + Context objectContext = null; + EventExecutorManager eventExecutorManager = null; + FoeiProcessManager foeiProcessManager = null; + + Map properties = new HashMap(0); + try { + objectContext = FoeiConfiguratorImpl.newContext(properties); + eventExecutorManager = new JCAEventExecutorManager((FoeiResourceAdapter)getResourceAdapter()); + foeiProcessManager = FoeiConfiguratorImpl.newFoeiProcessManager(properties); + FoeiConfiguratorImpl.loadEventThreadListeners(properties,eventExecutorManager); + } catch (Exception e) { + throw new ResourceException("Error while building childs objects:",e); + } + foeiContext = new FoeiContextImpl(foeiContextName,objectContext,eventExecutorManager,properties,foeiProcessManager); + } + + return new FoeiConnectionFactoryImpl(this, cm); + } + + /** + * @see javax.resource.spi.ManagedConnectionFactory#createConnectionFactory() + */ + public Object createConnectionFactory() throws ResourceException { + return createConnectionFactory(null); + } + + /** + * @see javax.resource.spi.ManagedConnectionFactory#createManagedConnection(javax.security.auth.Subject, javax.resource.spi.ConnectionRequestInfo) + */ + public ManagedConnection createManagedConnection(Subject subj,ConnectionRequestInfo conReqInfo) throws ResourceException { + return new FoeiManagedConnection(conReqInfo, writer, foeiContext); + } + + /** + * @see javax.resource.spi.ManagedConnectionFactory#matchManagedConnections(java.util.Set, javax.security.auth.Subject, javax.resource.spi.ConnectionRequestInfo) + */ + @SuppressWarnings("unchecked") + public ManagedConnection matchManagedConnections(Set set, Subject subj, ConnectionRequestInfo conReqInfo) throws ResourceException { + Iterator itr = set.iterator(); + if (itr.hasNext()) { + Object obj = itr.next(); + if (obj instanceof FoeiManagedConnection) { + return (FoeiManagedConnection)obj; + } + } + return null; + } + + /** + * @see javax.resource.spi.ManagedConnectionFactory#setLogWriter(java.io.PrintWriter) + */ + public void setLogWriter(PrintWriter out) throws ResourceException { + this.writer = out; + } + + /** + * @see javax.resource.spi.ManagedConnectionFactory#getLogWriter() + */ + public PrintWriter getLogWriter() throws ResourceException { + return writer; + } + + /** + * @see javax.resource.spi.ManagedConnectionFactory#hashCode() + */ + public int hashCode() { + if (foeiContextName == null) { + return super.hashCode(); + } else { + return foeiContextName.hashCode(); + } + } + + /** + * @see javax.resource.spi.ManagedConnectionFactory#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof FoeiManagedConnectionFactory)) { + return false; + } + if (foeiContextName == null) { + return false; + } + return foeiContextName.equals(((FoeiManagedConnectionFactory)obj).getFoeiContextName()); + } + + /** + * @return the foeiContextName + */ + public String getFoeiContextName() { + return foeiContextName; + } + + /** + * @param foeiContextName the foeiContextName to set + */ + public void setFoeiContextName(String foeiContextName) { + this.foeiContextName = foeiContextName; + } + + + + /** + * @see javax.resource.spi.ResourceAdapterAssociation#getResourceAdapter() + */ + public ResourceAdapter getResourceAdapter() { + return resourceAdapter; + } + + /** + * @see javax.resource.spi.ResourceAdapterAssociation#setResourceAdapter(javax.resource.spi.ResourceAdapter) + */ + public void setResourceAdapter(ResourceAdapter resourceAdapter) throws ResourceException { + this.resourceAdapter=resourceAdapter; + } +} diff --git a/src/com/idcanet/foei/ee/jca/cci/FoeiManagedConnectionMetaData.java b/src/com/idcanet/foei/ee/jca/cci/FoeiManagedConnectionMetaData.java new file mode 100644 index 0000000..38e2f0f --- /dev/null +++ b/src/com/idcanet/foei/ee/jca/cci/FoeiManagedConnectionMetaData.java @@ -0,0 +1,70 @@ +/* + * Copyright 2004-2008 IDCA. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and + * the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions + * and the following disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY IDCA AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IDCA OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the authors and + * should not be interpreted as representing official policies, either expressed or implied, of IDCA. + */ + +package com.idcanet.foei.ee.jca.cci; + +import javax.resource.ResourceException; +import javax.resource.spi.ManagedConnectionMetaData; + +/** + * + * + * @author Willem Cazander + * @version 1.0 Apr 19, 2008 + */ +public class FoeiManagedConnectionMetaData implements ManagedConnectionMetaData { + + /** Default instance of the class */ + public final static FoeiManagedConnectionMetaData INSTANCE = new FoeiManagedConnectionMetaData(); + + /** + * @see javax.resource.spi.ManagedConnectionMetaData#getEISProductName() + */ + public String getEISProductName() throws ResourceException { + return "Foei EE EIS"; + } + + /** + * @see javax.resource.spi.ManagedConnectionMetaData#getEISProductVersion() + */ + public String getEISProductVersion() throws ResourceException { + return "1.0"; + } + + /** + * @see javax.resource.spi.ManagedConnectionMetaData#getMaxConnections() + */ + public int getMaxConnections() throws ResourceException { + return 0; + } + + /** + * @see javax.resource.spi.ManagedConnectionMetaData#getUserName() + */ + public String getUserName() throws ResourceException { + return "IDCANET"; + } +} diff --git a/src/com/idcanet/foei/ee/jca/spi/FoeiActivationSpec.java b/src/com/idcanet/foei/ee/jca/spi/FoeiActivationSpec.java new file mode 100644 index 0000000..e80ddc3 --- /dev/null +++ b/src/com/idcanet/foei/ee/jca/spi/FoeiActivationSpec.java @@ -0,0 +1,92 @@ +/* + * Copyright 2004-2008 IDCA. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and + * the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions + * and the following disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY IDCA AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IDCA OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the authors and + * should not be interpreted as representing official policies, either expressed or implied, of IDCA. + */ + +package com.idcanet.foei.ee.jca.spi; + +import java.io.Serializable; + +import javax.resource.ResourceException; +import javax.resource.spi.ActivationSpec; +import javax.resource.spi.InvalidPropertyException; +import javax.resource.spi.ResourceAdapter; + +/** + * + * + * @author Willem Cazander + * @version 1.0 Apr 19, 2008 + */ +@SuppressWarnings("serial") +public class FoeiActivationSpec implements ActivationSpec, Serializable { + + /** The resource adapter */ + private transient ResourceAdapter resourceAdapter = null; + + private String beanName = null; + + /** + * @see javax.resource.spi.ActivationSpec#validate() + */ + public void validate() throws InvalidPropertyException { + if (beanName==null) { + throw new InvalidPropertyException("beanName is null,please set beanName property."); + } + if (beanName.isEmpty()) { + throw new InvalidPropertyException("beanName is empty,please set beanName property."); + } + } + + /** + * @see javax.resource.spi.ResourceAdapterAssociation#getResourceAdapter() + */ + public ResourceAdapter getResourceAdapter() { + return resourceAdapter; + } + + /** + * @see javax.resource.spi.ResourceAdapterAssociation#setResourceAdapter(javax.resource.spi.ResourceAdapter) + */ + public void setResourceAdapter(ResourceAdapter resourceAdapter) throws ResourceException { + if (resourceAdapter==null) { + throw new ResourceException("ResourceAdapter may not be null."); + } + this.resourceAdapter=resourceAdapter; + } + + /** + * @return the beanName + */ + public String getBeanName() { + return beanName; + } + + /** + * @param beanName the beanName to set + */ + public void setBeanName(String beanName) { + this.beanName = beanName; + } +} \ No newline at end of file diff --git a/src/com/idcanet/foei/ee/jca/spi/FoeiEventWrapper.java b/src/com/idcanet/foei/ee/jca/spi/FoeiEventWrapper.java new file mode 100644 index 0000000..cc82780 --- /dev/null +++ b/src/com/idcanet/foei/ee/jca/spi/FoeiEventWrapper.java @@ -0,0 +1,63 @@ +/* + * Copyright 2004-2008 IDCA. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and + * the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions + * and the following disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY IDCA AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IDCA OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the authors and + * should not be interpreted as representing official policies, either expressed or implied, of IDCA. + */ + +package com.idcanet.foei.ee.jca.spi; + +import java.util.logging.Logger; + +import javax.resource.spi.endpoint.MessageEndpoint; + +import com.idcanet.foei.event.AbstractEventInput; +import com.idcanet.foei.event.EventPort; +import com.idcanet.foei.event.IllegalEventPortNameException; + +/** + * + * + * @author Willem Cazander + * @version 1.0 Apr 19, 2008 + */ +@SuppressWarnings("serial") +public class FoeiEventWrapper extends AbstractEventInput { + + private Logger logger = Logger.getLogger(FoeiEventWrapper.class.getName()); + + /** + * @see com.idcanet.foei.event.AbstractEventInput#doEvent(com.idcanet.foei.event.EventPort, java.lang.Object) + */ + @Override + public void doEvent(EventPort eventPort, Object object) throws IllegalEventPortNameException { + MessageEndpoint endpoint = null; + //MessageEndpointFactory endpointFactory = null; //(MessageEndpointFactory)"endpointFactory"; + //endpoint = endpointFactory.createEndpoint(null); + if (endpoint != null) { + AbstractEventInput input = (AbstractEventInput) endpoint; + input.doEvent(eventPort, object); + } else { + logger.warning("MessageEndPoint is null."); + } + } +} \ No newline at end of file diff --git a/src/com/idcanet/foei/ee/jca/spi/FoeiResourceAdapter.java b/src/com/idcanet/foei/ee/jca/spi/FoeiResourceAdapter.java new file mode 100644 index 0000000..06318d1 --- /dev/null +++ b/src/com/idcanet/foei/ee/jca/spi/FoeiResourceAdapter.java @@ -0,0 +1,123 @@ +/* + * Copyright 2004-2008 IDCA. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and + * the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions + * and the following disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY IDCA AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IDCA OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the authors and + * should not be interpreted as representing official policies, either expressed or implied, of IDCA. + */ + +package com.idcanet.foei.ee.jca.spi; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.resource.ResourceException; +import javax.resource.spi.ActivationSpec; +import javax.resource.spi.BootstrapContext; +import javax.resource.spi.ResourceAdapter; +import javax.resource.spi.ResourceAdapterInternalException; +import javax.resource.spi.endpoint.MessageEndpoint; +import javax.resource.spi.endpoint.MessageEndpointFactory; +import javax.transaction.xa.XAResource; + +import com.idcanet.foei.server.FoeiContextManagerFactory; + +/** + * + * + * @author Willem Cazander + * @version 1.0 Apr 19, 2008 + */ +public class FoeiResourceAdapter implements ResourceAdapter { + + private Logger logger = Logger.getLogger(FoeiResourceAdapter.class.getName()); + + private BootstrapContext bootstrapContext = null; + + /** + * @see javax.resource.spi.ResourceAdapter#start(javax.resource.spi.BootstrapContext) + */ + public void start(BootstrapContext bootstrapContext) throws ResourceAdapterInternalException { + logger.info("Starting FoeiResourceAdapter"); + this.bootstrapContext=bootstrapContext; + } + + /** + * @see javax.resource.spi.ResourceAdapter#stop() + */ + public void stop() { + logger.info("Stopping FoeiResourceAdapter"); + try { + FoeiContextManagerFactory.getFoeiContextManager().destroyAll(); + } catch (Exception e) { + logger.log(Level.WARNING,"Error while shutdowning Foei: "+e.getMessage(),e); + throw new RuntimeException(e); + } + } + + /** + * @see javax.resource.spi.ResourceAdapter#getXAResources(javax.resource.spi.ActivationSpec[]) + */ + public XAResource[] getXAResources(ActivationSpec[] specs) throws ResourceException { + return null; + } + + /** + * @see javax.resource.spi.ResourceAdapter#endpointActivation(javax.resource.spi.endpoint.MessageEndpointFactory, javax.resource.spi.ActivationSpec) + */ + public void endpointActivation(MessageEndpointFactory endPointFactory,ActivationSpec spec) throws ResourceException { + + FoeiActivationSpec fac = (FoeiActivationSpec)spec; + + MessageEndpoint endPoint = endPointFactory.createEndpoint(null); + endPoint.release(); + + //endPoint. + + fac.getBeanName(); + // reg bean to foei context + } + + /** + * @see javax.resource.spi.ResourceAdapter#endpointDeactivation(javax.resource.spi.endpoint.MessageEndpointFactory, javax.resource.spi.ActivationSpec) + */ + public void endpointDeactivation(MessageEndpointFactory endPointFactory,ActivationSpec spec) { + //FoeiActivationSpec fac = (FoeiActivationSpec)spec; + + //for (FoeiProcess proc:foeiContext.getFoeiProcessManager().getFoeiProcesses()) { + // proc.removeEventObject(fac.getBeanName()); + //} + } + + /** + * @return the bootstrapContext + */ + public BootstrapContext getBootstrapContext() { + return bootstrapContext; + } + + /** + * @param bootstrapContext the bootstrapContext to set + */ + public void setBootstrapContext(BootstrapContext bootstrapContext) { + this.bootstrapContext = bootstrapContext; + } +} diff --git a/src/com/idcanet/foei/ee/jca/spi/JCAEventExecutorManager.java b/src/com/idcanet/foei/ee/jca/spi/JCAEventExecutorManager.java new file mode 100644 index 0000000..9a49917 --- /dev/null +++ b/src/com/idcanet/foei/ee/jca/spi/JCAEventExecutorManager.java @@ -0,0 +1,200 @@ +/* + * Copyright 2004-2008 IDCA. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and + * the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions + * and the following disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY IDCA AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IDCA OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the authors and + * should not be interpreted as representing official policies, either expressed or implied, of IDCA. + */ + +package com.idcanet.foei.ee.jca.spi; + +import com.idcanet.foei.core.EventExecutor; +import com.idcanet.foei.core.EventExecutorManager; +import com.idcanet.foei.core.EventThreadListener; +import com.idcanet.foei.core.FoeiContext; +import com.idcanet.foei.core.FoeiPortMessage; +import com.idcanet.foei.core.FoeiProcess; +import com.idcanet.foei.core.FoeiProcessFactory; +import com.idcanet.foei.core.impl.FoeiConfiguratorImpl; +import com.idcanet.foei.core.impl.FoeiProcessRunnableWrapper; +import com.idcanet.foei.event.EventPort; + +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.resource.spi.work.Work; +import javax.resource.spi.work.WorkException; + +/** + * Defines the EventExecutorManager implementation + * + * @author Willem Cazander + * @version 1.0 Apr 19, 2008 + */ +public class JCAEventExecutorManager implements EventExecutorManager { + + /** The logger to log to. */ + private Logger logger = null; + /** The EventThreadListeners */ + private List eventThreadListeners = null; + /** The class for the EventExecutor */ + private Class eventExecutorClass = null; + + private FoeiResourceAdapter foeiResourceAdapter = null; + /** + * Creates an EventExecutorManagerImpl ans inits the logger. + */ + public JCAEventExecutorManager(FoeiResourceAdapter foeiResourceAdapter) { + logger = Logger.getLogger(JCAEventExecutorManager.class.getName()); + eventThreadListeners = new ArrayList(1); + this.foeiResourceAdapter=foeiResourceAdapter; + } + + // ============= EventExecutorManager + + /** + * Executes an Event mostly send from an EventObject. + * @see EventExecutorManager#executeEvent(Object, EventPort) + */ + public void executeEvent(EventPort eventPort,Object eventObject) { + executeEvent(eventPort,eventObject,FoeiProcessFactory.getFoeiProcess()); + } + + /** + * Executes an EventPort with object in an FoeiProcess. + * @param eventPort + * @param eventObject + * @param foeiProcess + */ + public void executeEvent(EventPort eventPort,Object eventObject,FoeiProcess foeiProcess) { + + FoeiPortMessage msg = new FoeiPortMessage(); + msg.setEventObject(eventObject); + msg.setEventPort(eventPort); + foeiProcess.getWorkQueue().add(msg); + + if (foeiProcess.getExecutors().size()>3) { + return; + } + + EventExecutor e = null; + try { + e = (EventExecutor)eventExecutorClass.newInstance(); + } catch (Exception ee) { + logger.log(Level.WARNING,"Error Creating EventExecutor: "+ee.getMessage(),ee); + return; + } + e.setFoeiProcess(foeiProcess); + foeiProcess.getExecutors().add(e); + try { + logger.info("Setting work to EE workmanager"); + foeiResourceAdapter.getBootstrapContext().getWorkManager().scheduleWork(new WorkWrapper(e)); + } catch (WorkException ee) { + ee.printStackTrace(); + } + } + + /** + * Executes an event. + * @see EventExecutorManager#execute(Runnable) + */ + public void execute(Runnable runnable,FoeiProcess foeiProcess) { + try { + foeiResourceAdapter.getBootstrapContext().getWorkManager().scheduleWork(new WorkWrapper(new FoeiProcessRunnableWrapper(runnable,foeiProcess))); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Starts the ThreadPool + * @see EventExecutorManager#start() + */ + public void start(FoeiContext foeiContext) { + if(foeiContext==null) { + throw new NullPointerException("FoeiContext may not be null."); + } + logger.info("Starting EventExecutorManagerImpl"); + + try { + eventExecutorClass = FoeiConfiguratorImpl.newEventExecutorClass(foeiContext.getStartProperties()); + } catch (ClassNotFoundException cce) { + logger.log(Level.WARNING,"Error getting eventExecutor class: "+cce.getMessage(),cce); + throw new RuntimeException("Could not get EventExecutor class: "+cce.getMessage(),cce); + } + } + + /** + * Stops the ThreadPool + * @see EventExecutorManager#stop() + */ + public void stop(FoeiContext foeiContext) { + } + + /** + * @see EventExecutorManager#getEventThreadListeners() + */ + public List getEventThreadListeners() { + return eventThreadListeners; + } + + /** + * @see EventExecutorManager#addEventThreadListener(EventThreadListener) + */ + public void addEventThreadListener(EventThreadListener eventThreadListener) throws IllegalStateException { + if(eventThreadListener==null) { + throw new NullPointerException("eventThreadListener may not be null."); + } + eventThreadListeners.add(eventThreadListener); + } +} +class WorkWrapper implements Work { + + private Runnable run = null; + private Logger logger = Logger.getLogger(WorkWrapper.class.getName()); + + public WorkWrapper(Runnable run) { + this.run=run; + } + + /** + * @see javax.resource.spi.work.Work#release() + */ + public void release() { + logger.info("Releasing jca foei adapter."); + } + + /** + * @see java.lang.Runnable#run() + */ + public void run() { + try { + logger.info("Executing job: "+run); + run.run(); + } catch (Throwable e) { + logger.log(Level.WARNING,"Error in jca foei work unit: "+e.getMessage(),e); + } finally { + logger.info("Done running jobs"); + } + } +} \ No newline at end of file diff --git a/src/com/idcanet/foei/server/FoeiContextManager.java b/src/com/idcanet/foei/server/FoeiContextManager.java index a5a6c2f..6e8a71d 100644 --- a/src/com/idcanet/foei/server/FoeiContextManager.java +++ b/src/com/idcanet/foei/server/FoeiContextManager.java @@ -41,8 +41,8 @@ import java.util.logging.Logger; * @author Willem Cazander * @version 1.0 Feb 6, 2006 */ -public class FoeiContextManager -{ +public class FoeiContextManager { + /** The logger to log to. */ private Logger logger = null; /** All FoeiContext */ diff --git a/src/com/idcanet/foei/server/FoeiContextManagerFactory.java b/src/com/idcanet/foei/server/FoeiContextManagerFactory.java index 7528675..8a7a71b 100644 --- a/src/com/idcanet/foei/server/FoeiContextManagerFactory.java +++ b/src/com/idcanet/foei/server/FoeiContextManagerFactory.java @@ -32,8 +32,8 @@ package com.idcanet.foei.server; * @author Willem Cazander * @version 1.0 Feb 6, 2006 */ -public class FoeiContextManagerFactory -{ +public class FoeiContextManagerFactory { + /** */ static private FoeiContextManager foeiContextManager = null; diff --git a/src/com/idcanet/foei/server/startup/FoeiStartupListener.java b/src/com/idcanet/foei/server/startup/FoeiStartupListener.java index 0272d02..f7424aa 100644 --- a/src/com/idcanet/foei/server/startup/FoeiStartupListener.java +++ b/src/com/idcanet/foei/server/startup/FoeiStartupListener.java @@ -81,10 +81,7 @@ public class FoeiStartupListener implements ServletContextListener { Properties properties = new Properties(); properties.load(foeiProperties); foeiProperties.close(); - properties.put(FoeiConfigurator.ROOT_PATH,event.getServletContext().getRealPath("/")); foeiContextManager.createFoeiContext(properties); - - } catch (Exception e) { logger.log(Level.WARNING,"Error while starting FoeiContext: "+e.getMessage(),e); } diff --git a/tests/com/idcanet/foei/SimpleFoeiTests.java b/tests/com/idcanet/foei/SimpleFoeiTests.java index d34eed8..b40693f 100644 --- a/tests/com/idcanet/foei/SimpleFoeiTests.java +++ b/tests/com/idcanet/foei/SimpleFoeiTests.java @@ -66,7 +66,7 @@ public class SimpleFoeiTests extends TestCase { Properties properties = new Properties(); properties.load(foeiProperties); foeiProperties.close(); - properties.put(FoeiConfigurator.ROOT_PATH,"/tmp"); + //properties.put(FoeiConfigurator.ROOT_PATH,"/tmp"); foeiContextManager.createFoeiContext(properties); test0 = foeiContextManager.getFoeiContext("TEST-0"); @@ -126,7 +126,7 @@ public class SimpleFoeiTests extends TestCase { proc.getFoeiContext().getEventExecutorManager().executeEvent(in.getOutputPort(EventPort.OUTPUT), new Date(), proc); long endTime = System.currentTimeMillis(); System.out.println("Done sending in: "+(endTime-startTime)+" ms."); - Thread.sleep(50000); // todo: create destory context on end of event que + Thread.sleep(5000); // todo: create destory context on end of event que System.out.println("End speedtest"); test0.getFoeiProcessManager().destroyFoeiProcess("testSpeed0"); }