You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ode.apache.org by mr...@apache.org on 2006/11/09 22:54:20 UTC

svn commit: r473086 - in /incubator/ode/trunk: axis2/src/main/java/org/apache/ode/axis2/ bpel-api/src/main/java/org/apache/ode/bpel/iapi/ bpel-dd/src/main/xsd/ bpel-runtime/src/main/java/org/apache/ode/bpel/engine/ bpel-runtime/src/main/java/org/apache...

Author: mriou
Date: Thu Nov  9 13:54:19 2006
New Revision: 473086

URL: http://svn.apache.org/viewvc?view=rev&rev=473086
Log:
ODE-28 In-memory DAOs now work properly. It's just about adding an in-memory element under the process element in the deployment descriptor. Message exchanges and messages targeted at an in-memory process aren't persisted as well.

Modified:
    incubator/ode/trunk/axis2/src/main/java/org/apache/ode/axis2/ODEServer.java
    incubator/ode/trunk/bpel-api/src/main/java/org/apache/ode/bpel/iapi/ProcessConf.java
    incubator/ode/trunk/bpel-dd/src/main/xsd/dd.xsd
    incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/BpelEngineImpl.java
    incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/BpelProcess.java
    incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/BpelRuntimeContextImpl.java
    incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/BpelServerImpl.java
    incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/Contexts.java
    incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/WorkEvent.java
    incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/memdao/ProcessInstanceDaoImpl.java
    incubator/ode/trunk/bpel-scheduler-quartz/src/main/java/org/apache/ode/bpel/scheduler/quartz/QuartzSchedulerImpl.java
    incubator/ode/trunk/bpel-store/src/main/java/org/apache/ode/store/ProcessConfImpl.java
    incubator/ode/trunk/bpel-store/src/main/java/org/apache/ode/store/ProcessStoreImpl.java
    incubator/ode/trunk/bpel-test/src/test/java/org/apache/ode/test/BPELTest.java
    incubator/ode/trunk/dao-hibernate/src/main/java/org/apache/ode/daohib/bpel/MessageExchangeDaoImpl.java
    incubator/ode/trunk/jbi/src/main/java/org/apache/ode/jbi/OdeLifeCycle.java
    incubator/ode/trunk/utils/src/main/java/org/apache/ode/utils/DOMUtils.java

Modified: incubator/ode/trunk/axis2/src/main/java/org/apache/ode/axis2/ODEServer.java
URL: http://svn.apache.org/viewvc/incubator/ode/trunk/axis2/src/main/java/org/apache/ode/axis2/ODEServer.java?view=diff&rev=473086&r1=473085&r2=473086
==============================================================================
--- incubator/ode/trunk/axis2/src/main/java/org/apache/ode/axis2/ODEServer.java (original)
+++ incubator/ode/trunk/axis2/src/main/java/org/apache/ode/axis2/ODEServer.java Thu Nov  9 13:54:19 2006
@@ -415,6 +415,7 @@
         _scheduler.init();
 
         _server.setDaoConnectionFactory(_daoCF);
+        _server.setInMemDaoConnectionFactory(new org.apache.ode.bpel.memdao.BpelDAOConnectionFactoryImpl());
         _server.setEndpointReferenceContext(new EndpointReferenceContextImpl(this));
         _server.setMessageExchangeContext(new MessageExchangeContextImpl(this));
         _server.setBindingContext(new BindingContextImpl(this, _store));

Modified: incubator/ode/trunk/bpel-api/src/main/java/org/apache/ode/bpel/iapi/ProcessConf.java
URL: http://svn.apache.org/viewvc/incubator/ode/trunk/bpel-api/src/main/java/org/apache/ode/bpel/iapi/ProcessConf.java?view=diff&rev=473086&r1=473085&r2=473086
==============================================================================
--- incubator/ode/trunk/bpel-api/src/main/java/org/apache/ode/bpel/iapi/ProcessConf.java (original)
+++ incubator/ode/trunk/bpel-api/src/main/java/org/apache/ode/bpel/iapi/ProcessConf.java Thu Nov  9 13:54:19 2006
@@ -29,4 +29,9 @@
      * @return package name
      */
     String getProcessPackage();
+
+    /**
+     * @return true if the process should be executed only in-memory without being persisted
+     */
+    boolean isInMemory();
 }

Modified: incubator/ode/trunk/bpel-dd/src/main/xsd/dd.xsd
URL: http://svn.apache.org/viewvc/incubator/ode/trunk/bpel-dd/src/main/xsd/dd.xsd?view=diff&rev=473086&r1=473085&r2=473086
==============================================================================
--- incubator/ode/trunk/bpel-dd/src/main/xsd/dd.xsd (original)
+++ incubator/ode/trunk/bpel-dd/src/main/xsd/dd.xsd Thu Nov  9 13:54:19 2006
@@ -46,6 +46,13 @@
                                     deployed. </xs:documentation>
                             </xs:annotation>
                         </xs:element>
+                        <xs:element name="in-memory" minOccurs="0" maxOccurs="1" type="xs:boolean"
+                                    default="false">
+                            <xs:annotation>
+                                <xs:documentation>Should the process be persistent or only execute
+                                    in-memory.</xs:documentation>
+                            </xs:annotation>
+                        </xs:element>
 
                         <xs:element name="property"  minOccurs="0" maxOccurs="unbounded">
                             <xs:annotation>

Modified: incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/BpelEngineImpl.java
URL: http://svn.apache.org/viewvc/incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/BpelEngineImpl.java?view=diff&rev=473086&r1=473085&r2=473086
==============================================================================
--- incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/BpelEngineImpl.java (original)
+++ incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/BpelEngineImpl.java Thu Nov  9 13:54:19 2006
@@ -19,27 +19,13 @@
 
 package org.apache.ode.bpel.engine;
 
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-
-import javax.wsdl.Operation;
-import javax.wsdl.PortType;
-import javax.xml.namespace.QName;
-
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.ode.bpel.dao.MessageExchangeDAO;
 import org.apache.ode.bpel.dao.ProcessDAO;
 import org.apache.ode.bpel.dao.ProcessInstanceDAO;
-import org.apache.ode.bpel.iapi.BpelEngine;
-import org.apache.ode.bpel.iapi.BpelEngineException;
-import org.apache.ode.bpel.iapi.Endpoint;
-import org.apache.ode.bpel.iapi.Message;
-import org.apache.ode.bpel.iapi.MessageExchange;
-import org.apache.ode.bpel.iapi.MyRoleMessageExchange;
+import org.apache.ode.bpel.evt.BpelEvent;
+import org.apache.ode.bpel.iapi.*;
 import org.apache.ode.bpel.iapi.MessageExchange.MessageExchangePattern;
 import org.apache.ode.bpel.iapi.MessageExchange.Status;
 import org.apache.ode.bpel.iapi.MyRoleMessageExchange.CorrelationStatus;
@@ -48,6 +34,11 @@
 import org.apache.ode.bpel.o.OProcess;
 import org.apache.ode.utils.msg.MessageBundle;
 
+import javax.wsdl.Operation;
+import javax.wsdl.PortType;
+import javax.xml.namespace.QName;
+import java.util.*;
+
 /**
  * Implementation of the {@link BpelEngine} interface: provides the server
  * methods that should be invoked in the context of a transaction.
@@ -96,8 +87,14 @@
     public MyRoleMessageExchange createMessageExchange(String clientKey, QName targetService, String operation)
             throws BpelEngineException {
 
-        MessageExchangeDAO dao = _contexts.dao.getConnection().createMessageExchange(
-                MessageExchangeDAO.DIR_PARTNER_INVOKES_MYROLE);
+        BpelProcess target = route(targetService, null);
+
+        MessageExchangeDAO dao;
+        if (target == null || target.isInMemory()) {
+            dao = _contexts.inMemDao.getConnection().createMessageExchange(MessageExchangeDAO.DIR_PARTNER_INVOKES_MYROLE);
+        } else {
+            dao = _contexts.dao.getConnection().createMessageExchange(MessageExchangeDAO.DIR_PARTNER_INVOKES_MYROLE);
+        }
         dao.setCorrelationId(clientKey);
         dao.setCorrelationStatus(CorrelationStatus.UKNOWN_ENDPOINT.toString());
         dao.setPattern(MessageExchangePattern.UNKNOWN.toString());
@@ -106,7 +103,6 @@
         dao.setOperation(operation);
         MyRoleMessageExchangeImpl mex = new MyRoleMessageExchangeImpl(this, dao);
 
-        BpelProcess target = route(targetService, null);
         if (target != null)
             target.initMyRoleMex(mex);
 
@@ -229,7 +225,12 @@
     public void onScheduledJob(String jobId, Map<String, Object> jobDetail) {
         WorkEvent we = new WorkEvent(jobDetail);
 
-        ProcessInstanceDAO instance = _contexts.dao.getConnection().getInstance(we.getIID());
+        ProcessInstanceDAO instance;
+        if (we.isInMem())
+            instance = _contexts.inMemDao.getConnection().getInstance(we.getIID());
+        else
+            instance = _contexts.dao.getConnection().getInstance(we.getIID());
+
         if (instance == null) {
             __log.error(__msgs.msgScheduledJobReferencesUnknownInstance(we.getIID()));
             // nothing we can do, this instance is not in the database, it will
@@ -264,6 +265,14 @@
             ; // ignore
         } 
 
+    }
+
+    void fireEvent(BpelEvent event) {
+        // Note that the eventListeners list is a copy-on-write array, so need
+        // to mess with synchronization.
+        for (org.apache.ode.bpel.iapi.BpelEventListener l : _contexts.eventListeners) {
+            l.onEvent(event);
+        }
     }
 
     public MessageExchange getMessageExchangeByClientKey(String clientKey) {

Modified: incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/BpelProcess.java
URL: http://svn.apache.org/viewvc/incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/BpelProcess.java?view=diff&rev=473086&r1=473085&r2=473086
==============================================================================
--- incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/BpelProcess.java (original)
+++ incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/BpelProcess.java Thu Nov  9 13:54:19 2006
@@ -94,6 +94,7 @@
     private final List<MessageExchangeInterceptor> _mexInterceptors = new ArrayList<MessageExchangeInterceptor>();
 
     private ProcessStore _store;
+    private boolean _inMemory;
 
     public BpelProcess(QName pid, OProcess oprocess, Map<OPartnerLink, Endpoint> myRoleEndpointNames,
                        Map<OPartnerLink, Endpoint> initialPartners, BpelEventListener debugger,
@@ -105,6 +106,7 @@
         _expLangRuntimeRegistry = expLangRuntimeRegistry;
         _mexInterceptors.addAll(localMexInterceptors);
         _store = store;
+        _inMemory = store.getProcessConfiguration(_pid).isInMemory();
 
         for (OPartnerLink pl : _oprocess.getAllPartnerLinks()) {
             if (pl.hasMyRole()) {
@@ -674,7 +676,8 @@
     }
 
     ProcessDAO getProcessDAO() {
-        return _engine._contexts.dao.getConnection().getProcess(_pid);
+        if (_inMemory) return _engine._contexts.inMemDao.getConnection().getProcess(_pid);
+        else return _engine._contexts.dao.getConnection().getProcess(_pid);
     }
 
     static String genCorrelatorId(OPartnerLink plink, String opName) {
@@ -778,5 +781,9 @@
 
     void saveEvent(ProcessInstanceEvent event, ProcessInstanceDAO instanceDao) {
         instanceDao.insertBpelEvent(event);
+    }
+
+    public boolean isInMemory() {
+        return _inMemory;
     }
 }

Modified: incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/BpelRuntimeContextImpl.java
URL: http://svn.apache.org/viewvc/incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/BpelRuntimeContextImpl.java?view=diff&rev=473086&r1=473085&r2=473086
==============================================================================
--- incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/BpelRuntimeContextImpl.java (original)
+++ incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/BpelRuntimeContextImpl.java Thu Nov  9 13:54:19 2006
@@ -49,7 +49,10 @@
 import javax.xml.namespace.QName;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
 
 class BpelRuntimeContextImpl implements BpelRuntimeContext {
 
@@ -227,7 +230,7 @@
             Selector[] selectors) throws FaultException {
         if (BpelProcess.__log.isTraceEnabled())
             BpelProcess.__log.trace(ObjectPrinter.stringifyMethodEnter("select", new Object[] { "pickResponseChannel",
-                    pickResponseChannel, "timeout", timeout, "createInstance", Boolean.valueOf(createInstance),
+                    pickResponseChannel, "timeout", timeout, "createInstance", createInstance,
                     "selectors", selectors }));
 
         ProcessDAO processDao = _dao.getProcess();
@@ -246,8 +249,7 @@
         final String pickResponseChannelStr = pickResponseChannel.export();
 
         List<CorrelatorDAO> correlators = new ArrayList<CorrelatorDAO>(selectors.length);
-        for (int i = 0; i < selectors.length; ++i) {
-            Selector selector = selectors[i];
+        for (Selector selector : selectors) {
             String correlatorId = BpelProcess.genCorrelatorId(selector.plinkInstance.partnerLink, selector.opName);
             if (BpelProcess.__log.isDebugEnabled()) {
                 BpelProcess.__log.debug("SELECT: " + pickResponseChannel + ": USING CORRELATOR " + correlatorId);
@@ -591,6 +593,7 @@
         we.setIID(_dao.getInstanceId());
         we.setChannel(timerChannel.export());
         we.setType(WorkEvent.Type.TIMER);
+        we.setInMem(_bpelProcess.isInMemory());
         _bpelProcess._engine._contexts.scheduler.schedulePersistedJob(we.getDetail(), timeToFire);
     }
 
@@ -600,8 +603,8 @@
         we.setType(WorkEvent.Type.MATCHER);
         we.setCorrelatorId(correlatorId);
         we.setCorrelationKey(key);
-        _bpelProcess._engine._contexts.scheduler.schedulePersistedJob(we.getDetail(), new Date());
-
+        we.setInMem(_bpelProcess.isInMemory());
+        _bpelProcess._engine._contexts.scheduler.scheduleVolatileJob(false, we.getDetail(), new Date());
     }
 
     public String invoke(PartnerLinkInstance partnerLink, Operation operation, Element outgoingMessage,
@@ -746,6 +749,7 @@
                     WorkEvent we = new WorkEvent();
                     we.setIID(_iid);
                     we.setType(WorkEvent.Type.RESUME);
+                    we.setInMem(_bpelProcess.isInMemory());
                     _bpelProcess._engine._contexts.scheduler.schedulePersistedJob(we.getDetail(), new Date());
                 } catch (ContextException e) {
                     __log.error("Failed to schedule resume task.", e);
@@ -875,7 +879,6 @@
             break;
         }
         sendEvent(evt);
-
     }
 
     /**
@@ -887,6 +890,11 @@
         event.setProcessName(_dao.getProcess().getType());
         event.setProcessInstanceId(_dao.getInstanceId());
         _bpelProcess._debugger.onEvent(event);
+
+        // notify the listeners
+        _bpelProcess._engine.fireEvent(event);
+
+        // saving
         _bpelProcess.saveEvent(event);
     }
 
@@ -904,9 +912,7 @@
      */
     private void writeProperties(VariableInstance variable, Node value, XmlDataDAO dao) {
         if (variable.declaration.type instanceof OMessageVarType) {
-            for (Iterator<OProcess.OProperty> iter = variable.declaration.getOwner().properties.iterator(); iter
-                    .hasNext();) {
-                OProcess.OProperty property = iter.next();
+            for (OProcess.OProperty property : variable.declaration.getOwner().properties) {
                 OProcess.OPropertyAlias alias = property.getAlias(variable.declaration.type);
                 if (alias != null) {
                     try {
@@ -918,8 +924,8 @@
                     } catch (FaultException e) {
                         // This will fail as we're basically trying to extract properties on all
                         // received messages for optimization purposes.
-                         __log.debug("Couldn't extract property '" + property.toString()
-                                 + "' in property pre-extraction.", e);
+                        __log.debug("Couldn't extract property '" + property.toString()
+                                + "' in property pre-extraction.", e);
                     }
                 }
             }

Modified: incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/BpelServerImpl.java
URL: http://svn.apache.org/viewvc/incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/BpelServerImpl.java?view=diff&rev=473086&r1=473085&r2=473086
==============================================================================
--- incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/BpelServerImpl.java (original)
+++ incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/BpelServerImpl.java Thu Nov  9 13:54:19 2006
@@ -131,14 +131,6 @@
         _contexts.eventListeners.remove(listener);
     }
 
-    void fireEvent(BpelEvent event) {
-        // Note that the eventListeners list is a copy-on-write array, so need
-        // to mess with synchronization.
-        for (BpelEventListener l : _contexts.eventListeners) {
-            l.onEvent(event);
-        }
-    }
-
     public void stop() {
         _mngmtLock.writeLock().lock();
         try {
@@ -214,6 +206,10 @@
         _contexts.dao = daoCF;
     }
 
+    public void setInMemDaoConnectionFactory(BpelDAOConnectionFactory daoCF) {
+        _contexts.inMemDao = daoCF;
+    }
+
     public void setBindingContext(BindingContext bc) {
         _contexts.bindingContext = bc;
     }
@@ -397,21 +393,30 @@
 
     private boolean checkProcessExistence(final QName pid, final OProcess oprocess) {
         try {
-            boolean existed = _db.exec(new BpelDatabase.Callable<Boolean>() {
-                public Boolean run(BpelDAOConnection conn) throws Exception {
-                    // Hack, but at least for now we need to ensure that we
-                    // are
-                    // the only process with this process id.
-                    ProcessDAO old = conn.getProcess(pid);
-                    if (old != null) return true;
-
-                    ProcessDAO newDao = conn.createProcess(pid, oprocess.getQName());
-                    for (String correlator : oprocess.getCorrelators()) {
-                        newDao.addCorrelator(correlator);
-                    }
-                    return false;
+            boolean existed = true;
+            if (_contexts.store.getProcessConfiguration(pid).isInMemory()) {
+                existed = false;
+                ProcessDAO newDao = _contexts.inMemDao.getConnection().createProcess(pid, oprocess.getQName());
+                for (String correlator : oprocess.getCorrelators()) {
+                    newDao.addCorrelator(correlator);
                 }
-            });
+            } else {
+                existed = _db.exec(new BpelDatabase.Callable<Boolean>() {
+                    public Boolean run(BpelDAOConnection conn) throws Exception {
+                        // Hack, but at least for now we need to ensure that we
+                        // are
+                        // the only process with this process id.
+                        ProcessDAO old = conn.getProcess(pid);
+                        if (old != null) return true;
+
+                        ProcessDAO newDao = conn.createProcess(pid, oprocess.getQName());
+                        for (String correlator : oprocess.getCorrelators()) {
+                            newDao.addCorrelator(correlator);
+                        }
+                        return false;
+                    }
+                });
+            }
             if (__log.isDebugEnabled()) {
                 if (existed) __log.debug("Process runtime already exist (" + pid + "), no need to create.");
                 else __log.debug("Created new process runtime " + pid);

Modified: incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/Contexts.java
URL: http://svn.apache.org/viewvc/incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/Contexts.java?view=diff&rev=473086&r1=473085&r2=473086
==============================================================================
--- incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/Contexts.java (original)
+++ incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/Contexts.java Thu Nov  9 13:54:19 2006
@@ -42,6 +42,7 @@
     BindingContext bindingContext;
 
     BpelDAOConnectionFactory dao;
+    BpelDAOConnectionFactory inMemDao;
 
     ProcessStore store;
 

Modified: incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/WorkEvent.java
URL: http://svn.apache.org/viewvc/incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/WorkEvent.java?view=diff&rev=473086&r1=473085&r2=473086
==============================================================================
--- incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/WorkEvent.java (original)
+++ incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/engine/WorkEvent.java Thu Nov  9 13:54:19 2006
@@ -19,11 +19,11 @@
 
 package org.apache.ode.bpel.engine;
 
+import org.apache.ode.bpel.common.CorrelationKey;
+
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.ode.bpel.common.CorrelationKey;
-
 /**
  * Wrapper around job detail map.
  * 
@@ -98,6 +98,14 @@
     
     public void setCorrelationKey(CorrelationKey ckey) {
         _jobDetail.put("ckey", ckey == null ? null : ckey.toCanonicalString());
+    }
+
+    public void setInMem(boolean inmem) {
+        _jobDetail.put("inmem", inmem);
+    }
+
+    public boolean isInMem() {
+        return (Boolean)_jobDetail.get("inmem");
     }
 }
 

Modified: incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/memdao/ProcessInstanceDaoImpl.java
URL: http://svn.apache.org/viewvc/incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/memdao/ProcessInstanceDaoImpl.java?view=diff&rev=473086&r1=473085&r2=473086
==============================================================================
--- incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/memdao/ProcessInstanceDaoImpl.java (original)
+++ incubator/ode/trunk/bpel-runtime/src/main/java/org/apache/ode/bpel/memdao/ProcessInstanceDaoImpl.java Thu Nov  9 13:54:19 2006
@@ -6,30 +6,13 @@
 package org.apache.ode.bpel.memdao;
 
 import org.apache.ode.bpel.common.ProcessState;
-import org.apache.ode.bpel.dao.ActivityRecoveryDAO;
-import org.apache.ode.bpel.dao.BpelDAOConnection;
-import org.apache.ode.bpel.dao.CorrelationSetDAO;
-import org.apache.ode.bpel.dao.CorrelatorDAO;
-import org.apache.ode.bpel.dao.FaultDAO;
-import org.apache.ode.bpel.dao.ProcessDAO;
-import org.apache.ode.bpel.dao.ProcessInstanceDAO;
-import org.apache.ode.bpel.dao.ScopeDAO;
-import org.apache.ode.bpel.dao.XmlDataDAO;
+import org.apache.ode.bpel.dao.*;
 import org.apache.ode.bpel.evt.ProcessInstanceEvent;
 import org.apache.ode.utils.QNameUtils;
 import org.w3c.dom.Element;
 
 import javax.xml.namespace.QName;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 /**
  * A very simple, in-memory implementation of the {@link ProcessInstanceDAO}
@@ -84,10 +67,6 @@
         _conn = conn;
     }
 
-    public BpelDAOConnection getConnection() {
-        return _conn;
-    }
-
     public XmlDataDAO[] getVariables(String variableName, int scopeModelId) {
         ArrayList<XmlDataDAO> res = new ArrayList<XmlDataDAO>();
         for (ScopeDAO scope : _scopes.values()) {
@@ -313,7 +292,7 @@
     }
 
     public void createActivityRecovery(String channel, long activityId, String reason, Date dateTime, Element data,
-            String[] actions, int retries) {
+                                       String[] actions, int retries) {
         _activityRecoveries
                 .put(channel, new ActivityRecoveryDAOImpl(channel, activityId, reason, dateTime, data, actions, retries));
         _failureCount = _activityRecoveries.size();
@@ -346,7 +325,7 @@
         private int _retries;
 
         ActivityRecoveryDAOImpl(String channel, long activityId, String reason, Date dateTime, Element details, String[] actions,
-                int retries) {
+                                int retries) {
             _activityId = activityId;
             _channel = channel;
             _reason = reason;
@@ -395,7 +374,10 @@
     void removeRoutes(String routeGroupId) {
         for (CorrelatorDaoImpl correlator : _processDao._correlators.values())
             correlator._removeRoutes(routeGroupId, this);
+    }
 
+    public BpelDAOConnection getConnection() {
+        return _conn;
     }
 
 }

Modified: incubator/ode/trunk/bpel-scheduler-quartz/src/main/java/org/apache/ode/bpel/scheduler/quartz/QuartzSchedulerImpl.java
URL: http://svn.apache.org/viewvc/incubator/ode/trunk/bpel-scheduler-quartz/src/main/java/org/apache/ode/bpel/scheduler/quartz/QuartzSchedulerImpl.java?view=diff&rev=473086&r1=473085&r2=473086
==============================================================================
--- incubator/ode/trunk/bpel-scheduler-quartz/src/main/java/org/apache/ode/bpel/scheduler/quartz/QuartzSchedulerImpl.java (original)
+++ incubator/ode/trunk/bpel-scheduler-quartz/src/main/java/org/apache/ode/bpel/scheduler/quartz/QuartzSchedulerImpl.java Thu Nov  9 13:54:19 2006
@@ -19,24 +19,13 @@
 
 package org.apache.ode.bpel.scheduler.quartz;
 
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-
-import javax.sql.DataSource;
-import javax.transaction.TransactionManager;
-
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.quartz.JobDataMap;
-import org.quartz.JobDetail;
-import org.quartz.JobExecutionContext;
-import org.quartz.SchedulerException;
-import org.quartz.SimpleTrigger;
-import org.quartz.Trigger;
+import org.apache.ode.bpel.iapi.BpelServer;
+import org.apache.ode.bpel.iapi.ContextException;
+import org.apache.ode.bpel.iapi.Scheduler;
+import org.apache.ode.utils.GUID;
+import org.quartz.*;
 import org.quartz.core.QuartzScheduler;
 import org.quartz.core.QuartzSchedulerResources;
 import org.quartz.core.SchedulingContext;
@@ -46,10 +35,15 @@
 import org.quartz.spi.ClassLoadHelper;
 import org.quartz.spi.ThreadPool;
 import org.quartz.utils.DBConnectionManager;
-import org.apache.ode.bpel.iapi.BpelServer;
-import org.apache.ode.bpel.iapi.ContextException;
-import org.apache.ode.bpel.iapi.Scheduler;
-import org.apache.ode.utils.GUID;
+
+import javax.sql.DataSource;
+import javax.transaction.TransactionManager;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
 
 /**
  * Base class that can be used to quickly implement a persistent scheduler.
@@ -174,6 +168,7 @@
     jobDetail.setRequestsRecovery(true);
     Trigger trigger = new SimpleTrigger(jobDetail.getName() + ".trigger",
         org.quartz.Scheduler.DEFAULT_GROUP, when, null, 0, 0L);
+      trigger.setVolatility(volatil);
 
     try {
       _quartz.scheduleJob(jobDetail, trigger);

Modified: incubator/ode/trunk/bpel-store/src/main/java/org/apache/ode/store/ProcessConfImpl.java
URL: http://svn.apache.org/viewvc/incubator/ode/trunk/bpel-store/src/main/java/org/apache/ode/store/ProcessConfImpl.java?view=diff&rev=473086&r1=473085&r2=473086
==============================================================================
--- incubator/ode/trunk/bpel-store/src/main/java/org/apache/ode/store/ProcessConfImpl.java (original)
+++ incubator/ode/trunk/bpel-store/src/main/java/org/apache/ode/store/ProcessConfImpl.java Thu Nov  9 13:54:19 2006
@@ -20,6 +20,7 @@
     private String packageName;
     private Map<QName,Node> props;
     private boolean active;
+    private boolean inMemory;
 
     public Date getDeployDate() {
         return deployDate;
@@ -75,5 +76,13 @@
 
     public void setProps(Map<QName, Node> props) {
         this.props = props;
+    }
+
+    public boolean isInMemory() {
+        return inMemory;
+    }
+
+    public void setInMemory(boolean inMemory) {
+        this.inMemory = inMemory;
     }
 }

Modified: incubator/ode/trunk/bpel-store/src/main/java/org/apache/ode/store/ProcessStoreImpl.java
URL: http://svn.apache.org/viewvc/incubator/ode/trunk/bpel-store/src/main/java/org/apache/ode/store/ProcessStoreImpl.java?view=diff&rev=473086&r1=473085&r2=473086
==============================================================================
--- incubator/ode/trunk/bpel-store/src/main/java/org/apache/ode/store/ProcessStoreImpl.java (original)
+++ incubator/ode/trunk/bpel-store/src/main/java/org/apache/ode/store/ProcessStoreImpl.java Thu Nov  9 13:54:19 2006
@@ -496,6 +496,7 @@
     private ProcessConf buildConf(ProcessConfDAO dao) {
         DeploymentUnit du = _deploymentUnits.get(dao.getProcessId());
         ProcessConfImpl conf = new ProcessConfImpl();
+        TDeployment.Process processInfo = getProcessInfo(dao.getProcessId());
         conf.setActive(dao.isActive());
         conf.setDeployDate(dao.getDeployDate());
         conf.setDeployer(dao.getDeployer());
@@ -503,6 +504,7 @@
         conf.setPackageName(du.getDeployDir().getName());
         conf.setProcessId(dao.getProcessId());
         conf.setProps(dao.getProperties());
+        conf.setInMemory(processInfo.isSetInMemory() && processInfo.getInMemory());
         return conf;
     }
 

Modified: incubator/ode/trunk/bpel-test/src/test/java/org/apache/ode/test/BPELTest.java
URL: http://svn.apache.org/viewvc/incubator/ode/trunk/bpel-test/src/test/java/org/apache/ode/test/BPELTest.java?view=diff&rev=473086&r1=473085&r2=473086
==============================================================================
--- incubator/ode/trunk/bpel-test/src/test/java/org/apache/ode/test/BPELTest.java (original)
+++ incubator/ode/trunk/bpel-test/src/test/java/org/apache/ode/test/BPELTest.java Thu Nov  9 13:54:19 2006
@@ -47,7 +47,8 @@
 		server = new BpelServerImpl();
 		mexContext = new MessageExchangeContextImpl();
 		server.setDaoConnectionFactory(new BpelDAOConnectionFactoryImpl());
-		server.setScheduler(new TestScheduler());
+        server.setInMemDaoConnectionFactory(new BpelDAOConnectionFactoryImpl());
+        server.setScheduler(new TestScheduler());
 		server.setBindingContext(new BindingContextImpl());
 		server.setMessageExchangeContext(mexContext);
         store = new ProcessStoreImpl(null, null, new DeploymentManagerImpl(), null);

Modified: incubator/ode/trunk/dao-hibernate/src/main/java/org/apache/ode/daohib/bpel/MessageExchangeDaoImpl.java
URL: http://svn.apache.org/viewvc/incubator/ode/trunk/dao-hibernate/src/main/java/org/apache/ode/daohib/bpel/MessageExchangeDaoImpl.java?view=diff&rev=473086&r1=473085&r2=473086
==============================================================================
--- incubator/ode/trunk/dao-hibernate/src/main/java/org/apache/ode/daohib/bpel/MessageExchangeDaoImpl.java (original)
+++ incubator/ode/trunk/dao-hibernate/src/main/java/org/apache/ode/daohib/bpel/MessageExchangeDaoImpl.java Thu Nov  9 13:54:19 2006
@@ -19,11 +19,7 @@
 
 package org.apache.ode.daohib.bpel;
 
-import org.apache.ode.bpel.dao.MessageDAO;
-import org.apache.ode.bpel.dao.MessageExchangeDAO;
-import org.apache.ode.bpel.dao.PartnerLinkDAO;
-import org.apache.ode.bpel.dao.ProcessDAO;
-import org.apache.ode.bpel.dao.ProcessInstanceDAO;
+import org.apache.ode.bpel.dao.*;
 import org.apache.ode.daohib.SessionManager;
 import org.apache.ode.daohib.bpel.hobj.HMessage;
 import org.apache.ode.daohib.bpel.hobj.HMessageExchange;
@@ -42,6 +38,11 @@
 
     private HMessageExchange _hself;
 
+    // Used when provided process and instance aren't hibernate implementations. The relation
+    // therefore can't be persisted. Used for in-mem DAOs so that doesn't matter much. 
+    private ProcessDAO _externalProcess;
+    private ProcessInstanceDAO _externalInstance;
+
     public MessageExchangeDaoImpl(SessionManager sm, HMessageExchange mex) {
         super(sm, mex);
         _hself = mex;
@@ -234,22 +235,33 @@
     }
 
     public ProcessDAO getProcess() {
-        return _hself.getProcess() == null ? null : new ProcessDaoImpl(_sm, _hself.getProcess());
+        if (_externalProcess != null) return _externalProcess;
+        else return _hself.getProcess() == null ? null : new ProcessDaoImpl(_sm, _hself.getProcess());
     }
 
     public void setProcess(ProcessDAO process) {
-        _hself.setProcess(process == null ? null : (HProcess) ((ProcessDaoImpl) process).getHibernateObj());
-        update();
+        if (process == null || process instanceof ProcessDaoImpl) {
+            _hself.setProcess(process == null ? null : (HProcess) ((ProcessDaoImpl) process).getHibernateObj());
+            update();
+        } else {
+            _externalProcess = process;
+        }
     }
 
     public void setInstance(ProcessInstanceDAO instance) {
+        if (instance == null || instance instanceof ProcessInstanceDaoImpl) {
         _hself.setInstance(instance == null ? null : (HProcessInstance) ((ProcessInstanceDaoImpl) instance)
                 .getHibernateObj());
         update();
+        } else {
+            _externalInstance = instance;
+        }
+
     }
 
     public ProcessInstanceDAO getInstance() {
-        return _hself.getInstance() == null ? null : new ProcessInstanceDaoImpl(_sm, _hself.getInstance());
+        if (_externalInstance != null) return _externalInstance;
+        else return _hself.getInstance() == null ? null : new ProcessInstanceDaoImpl(_sm, _hself.getInstance());
     }
 
     public char getDirection() {

Modified: incubator/ode/trunk/jbi/src/main/java/org/apache/ode/jbi/OdeLifeCycle.java
URL: http://svn.apache.org/viewvc/incubator/ode/trunk/jbi/src/main/java/org/apache/ode/jbi/OdeLifeCycle.java?view=diff&rev=473086&r1=473085&r2=473086
==============================================================================
--- incubator/ode/trunk/jbi/src/main/java/org/apache/ode/jbi/OdeLifeCycle.java (original)
+++ incubator/ode/trunk/jbi/src/main/java/org/apache/ode/jbi/OdeLifeCycle.java Thu Nov  9 13:54:19 2006
@@ -250,6 +250,7 @@
 
         _ode._store = new ProcessStoreImpl(new File("."), _ode._dataSource, _ode.getTransactionManager());
 
+        _ode._server.setInMemDaoConnectionFactory(new org.apache.ode.bpel.memdao.BpelDAOConnectionFactoryImpl());        
         _ode._server.setDaoConnectionFactory(_ode._daocf);
         _ode._server.setEndpointReferenceContext(_ode._eprContext);
         _ode._server.setMessageExchangeContext(_ode._mexContext);

Modified: incubator/ode/trunk/utils/src/main/java/org/apache/ode/utils/DOMUtils.java
URL: http://svn.apache.org/viewvc/incubator/ode/trunk/utils/src/main/java/org/apache/ode/utils/DOMUtils.java?view=diff&rev=473086&r1=473085&r2=473086
==============================================================================
--- incubator/ode/trunk/utils/src/main/java/org/apache/ode/utils/DOMUtils.java (original)
+++ incubator/ode/trunk/utils/src/main/java/org/apache/ode/utils/DOMUtils.java Thu Nov  9 13:54:19 2006
@@ -18,20 +18,11 @@
  */
 package org.apache.ode.utils;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-
-import javax.xml.namespace.QName;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-
+import com.sun.org.apache.xerces.internal.dom.DOMOutputImpl;
+import com.sun.org.apache.xerces.internal.impl.Constants;
+import com.sun.org.apache.xml.internal.serialize.DOMSerializerImpl;
+import com.sun.org.apache.xml.internal.serialize.OutputFormat;
+import com.sun.org.apache.xml.internal.serialize.XMLSerializer;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.commons.pool.BasePoolableObjectFactory;
@@ -39,763 +30,763 @@
 import org.apache.commons.pool.PoolableObjectFactory;
 import org.apache.commons.pool.impl.GenericObjectPool;
 import org.apache.ode.utils.sax.LoggingErrorHandler;
-import org.w3c.dom.Attr;
-import org.w3c.dom.CharacterData;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
+import org.w3c.dom.*;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
 
-import com.sun.org.apache.xerces.internal.dom.DOMOutputImpl;
-import com.sun.org.apache.xerces.internal.impl.Constants;
-import com.sun.org.apache.xml.internal.serialize.DOMSerializerImpl;
-import com.sun.org.apache.xml.internal.serialize.OutputFormat;
-import com.sun.org.apache.xml.internal.serialize.XMLSerializer;
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.*;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
 
 /**
  * Utility class for dealing with the Document Object Model (DOM).
  */
 public class DOMUtils {
 
-  private static Log __log = LogFactory.getLog(DOMUtils.class);
+    private static Log __log = LogFactory.getLog(DOMUtils.class);
+
+    /** The namespaceURI represented by the prefix <code>xmlns</code>. */
+    public static final String NS_URI_XMLNS = "http://www.w3.org/2000/xmlns/";
+
+    private static DocumentBuilderFactory __documentBuilderFactory ;
+    private static ObjectPool __documentBuilderPool;
+
+    static {
+        initDocumentBuilderPool();
+    }
+
+    /**
+     * Initialize the document-builder pool.
+     */
+    private static void initDocumentBuilderPool() {
+        DocumentBuilderFactory f = XMLParserUtils.getDocumentBuilderFactory();
+        f.setNamespaceAware(true);
+        __documentBuilderFactory = f;
+
+        PoolableObjectFactory pof = new BasePoolableObjectFactory() {
+            public Object makeObject() throws Exception {
+                if (__log.isDebugEnabled()) {
+                    __log.debug("makeObject: Creating new DocumentBuilder.");
+                }
+
+                DocumentBuilder db = null;
+                synchronized (__documentBuilderFactory) {
+                    try {
+                        db = __documentBuilderFactory.newDocumentBuilder();
+                        db.setErrorHandler(new LoggingErrorHandler());
+                    } catch (ParserConfigurationException e) {
+                        __log.error(e);
+                        throw new RuntimeException(e);
+                    }
+                }
+                return db;
+            }
+
+            public void destroyObject(Object obj) throws Exception {
+                if (__log.isDebugEnabled())
+                    __log.debug("destroyObject: Removing DocumentBuilder from pool: " + obj);
+            }
+        };
+
+        GenericObjectPool.Config poolCfg = new GenericObjectPool.Config();
+        poolCfg.maxActive = Integer.MAX_VALUE;
+        poolCfg.maxIdle = 20;
+        poolCfg.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
+        __documentBuilderPool = new GenericObjectPool(pof, poolCfg);
+    }
+
+    /**
+     * Returns the value of an attribute of an element. Returns null if the
+     * attribute is not found (whereas Element.getAttribute returns "" if an
+     * attrib is not found).
+     *
+     * @param el Element whose attrib is looked for
+     * @param attrName name of attribute to look for
+     *
+     * @return the attribute value
+     */
+    static public String getAttribute(Element el, String attrName) {
+        String sRet = null;
+        Attr attr = el.getAttributeNode(attrName);
+        if (attr != null) {
+            sRet = attr.getValue();
+        }
+        return sRet;
+    }
 
-  /** The namespaceURI represented by the prefix <code>xmlns</code>. */
-  public static final String NS_URI_XMLNS = "http://www.w3.org/2000/xmlns/";
+    static public String prettyPrint(Element e) throws IOException {
+        OutputFormat format = new OutputFormat(e.getOwnerDocument());
+        format.setLineWidth(65);
+        format.setIndenting(true);
+        format.setIndent(2);
+        StringWriter out = new StringWriter();
+        XMLSerializer serializer = new XMLSerializer(out, format);
+        serializer.serialize(e);
 
-  private static DocumentBuilderFactory __documentBuilderFactory ;
-  private static ObjectPool __documentBuilderPool;
+        return out.toString();
+    }
 
-  static {
-    initDocumentBuilderPool();
-  }
-
-  /**
-   * Initialize the document-builder pool.
-   */
-  private static void initDocumentBuilderPool() {
-    DocumentBuilderFactory f = XMLParserUtils.getDocumentBuilderFactory();
-    f.setNamespaceAware(true);
-    __documentBuilderFactory = f;
-
-    PoolableObjectFactory pof = new BasePoolableObjectFactory() {
-      public Object makeObject() throws Exception {
-        if (__log.isDebugEnabled()) {
-          __log.debug("makeObject: Creating new DocumentBuilder.");
-        }
-
-        DocumentBuilder db = null;
-        synchronized (__documentBuilderFactory) {
-          try {
-            db = __documentBuilderFactory.newDocumentBuilder();
-            db.setErrorHandler(new LoggingErrorHandler());
-          } catch (ParserConfigurationException e) {
-            __log.error(e);
-            throw new RuntimeException(e);
-          }
-        }
-        return db;
-      }
-
-      public void destroyObject(Object obj) throws Exception {
-        if (__log.isDebugEnabled())
-          __log.debug("destroyObject: Removing DocumentBuilder from pool: " + obj);
-      }
-    };
-
-    GenericObjectPool.Config poolCfg = new GenericObjectPool.Config();
-    poolCfg.maxActive = Integer.MAX_VALUE;
-    poolCfg.maxIdle = 20;
-    poolCfg.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_GROW;
-    __documentBuilderPool = new GenericObjectPool(pof, poolCfg);
-  }
-
-  /**
-   * Returns the value of an attribute of an element. Returns null if the
-   * attribute is not found (whereas Element.getAttribute returns "" if an
-   * attrib is not found).
-   *
-   * @param el Element whose attrib is looked for
-   * @param attrName name of attribute to look for
-   *
-   * @return the attribute value
-   */
-  static public String getAttribute(Element el, String attrName) {
-    String sRet = null;
-    Attr attr = el.getAttributeNode(attrName);
-    if (attr != null) {
-      sRet = attr.getValue();
-    }
-    return sRet;
-  }
-  
-  static public String prettyPrint(Element e) throws IOException {
-    OutputFormat format = new OutputFormat(e.getOwnerDocument());  
-    format.setLineWidth(65);  
-    format.setIndenting(true);  
-    format.setIndent(2);  
-    StringWriter out = new StringWriter();
-    XMLSerializer serializer = new XMLSerializer(out, format);  
-    serializer.serialize(e); 
-    
-    return out.toString();
-  }
-
-  /**
-   * Returns the value of an attribute of an element. Returns null if the
-   * attribute is not found (whereas Element.getAttributeNS returns "" if an
-   * attrib is not found).
-   *
-   * @param el Element whose attrib is looked for
-   * @param namespaceURI namespace URI of attribute to look for
-   * @param localPart local part of attribute to look for
-   *
-   * @return the attribute value
-   */
-  static public String getAttributeNS(Element el, String namespaceURI,
-      String localPart) {
-    String sRet = null;
-    Attr attr = el.getAttributeNodeNS(namespaceURI, localPart);
-    if (attr != null) {
-      sRet = attr.getValue();
-    }
-    return sRet;
-  }
-
-  /**
-   * Concat all the text and cdata node children of this elem and return the
-   * resulting text.
-   *
-   * @param parentEl the element whose cdata/text node values are to be
-   *        combined.
-   *
-   * @return the concatanated string.
-   */
-  static public String getChildCharacterData(Element parentEl) {
-    if (parentEl == null) { return null; }
-    Node tempNode = parentEl.getFirstChild();
-    StringBuffer strBuf = new StringBuffer();
-    CharacterData charData;
-    while (tempNode != null) {
-      switch (tempNode.getNodeType()) {
-      case Node.TEXT_NODE:
-      case Node.CDATA_SECTION_NODE:
-        charData = (CharacterData) tempNode;
-        strBuf.append(charData.getData());
-        break;
-      }
-      tempNode = tempNode.getNextSibling();
-    }
-    return strBuf.toString();
-  }
-
-  /**
-   * DOCUMENTME
-   *
-   * @param el DOCUMENTME
-   * @param id DOCUMENTME
-   *
-   * @return DOCUMENTME
-   */
-  public static Element getElementByID(Element el, String id) {
-    if (el == null) { return null; }
-    String thisId = el.getAttribute("id");
-    if (id.equals(thisId)) { return el; }
-    NodeList list = el.getChildNodes();
-    for (int i = 0; i < list.getLength(); i++) {
-      Node node = list.item(i);
-      if (node instanceof Element) {
-        Element ret = getElementByID((Element) node, id);
-        if (ret != null) { return ret; }
-      }
-    }
-    return null;
-  }
-
-  /**
-   * Return the first child element of the given element. Null if no children
-   * are found.
-   *
-   * @param elem Element whose child is to be returned
-   *
-   * @return the first child element.
-   */
-  public static Element getFirstChildElement(Element elem) {
-    if (elem == null)
-      throw new NullPointerException("elem parameter must not be null!");
-    
-    for (Node n = elem.getFirstChild(); n != null; n = n.getNextSibling()) {
-      if (n.getNodeType() == Node.ELEMENT_NODE) { return (Element) n; }
-    }
-    return null;
-  }
-
-  /**
-   * Given a prefix and a node, return the namespace URI that the prefix has
-   * been associated with. This method is useful in resolving the namespace
-   * URI of attribute values which are being interpreted as QNames. If prefix
-   * is null, this method will return the default namespace.
-   *
-   * @param context the starting node (looks up recursively from here)
-   * @param prefix the prefix to find an xmlns:prefix=uri for
-   *
-   * @return the namespace URI or null if not found
-   */
-  public static String getNamespaceURIFromPrefix(Node context, String prefix) {
-    short nodeType = context.getNodeType();
-    Node tempNode = null;
-    switch (nodeType) {
-    case Node.ATTRIBUTE_NODE: {
-      tempNode = ((Attr) context).getOwnerElement();
-      break;
-    }
-    case Node.ELEMENT_NODE: {
-      tempNode = context;
-      break;
-    }
-    default: {
-      tempNode = context.getParentNode();
-      break;
-    }
-    }
-    while ((tempNode != null) && (tempNode.getNodeType() == Node.ELEMENT_NODE)) {
-      Element tempEl = (Element) tempNode;
-      String namespaceURI = (prefix == null) ? getAttribute(tempEl, "xmlns")
-          : getAttributeNS(tempEl, NS_URI_XMLNS, prefix);
-      if (namespaceURI != null) {
-        return namespaceURI;
-      }
-      tempNode = tempEl.getParentNode();
-    }
-    return null;
-  }
-
-  /**
-   * Return the next sibling element of the given element. Null if no more
-   * sibling elements are found.
-   *
-   * @param elem Element whose sibling element is to be returned
-   *
-   * @return the next sibling element.
-   */
-  public static Element getNextSiblingElement(Element elem) {
-    for (Node n = elem.getNextSibling(); n != null; n = n.getNextSibling()) {
-      if (n.getNodeType() == Node.ELEMENT_NODE) { return (Element) n; }
-    }
-    return null;
-  }
-
-  /**
-   * DOCUMENTME
-   *
-   * @param el DOCUMENTME
-   * @param attrName DOCUMENTME
-   *
-   * @return DOCUMENTME
-   *
-   * @throws IllegalArgumentException DOCUMENTME
-   */
-  public static QName getQualifiedAttributeValue(Element el, String attrName)
-      throws IllegalArgumentException {
-    String attrValue = DOMUtils.getAttribute(el, attrName);
-    if (attrValue != null) {
-      int index = attrValue.indexOf(':');
-      String attrValuePrefix = (index != -1) ? attrValue.substring(0, index)
-          : null;
-      String attrValueLocalPart = attrValue.substring(index + 1);
-      String attrValueNamespaceURI = DOMUtils.getNamespaceURIFromPrefix(el,
-          attrValuePrefix);
-      if (attrValueNamespaceURI != null) {
-        return new QName(attrValueNamespaceURI, attrValueLocalPart);
-      }
-      throw new IllegalArgumentException("Unable to determine "
-            + "namespace of '"
-            + ((attrValuePrefix != null) ? (attrValuePrefix + ":") : "")
-            + attrValueLocalPart + "'.");
-    }
-    return null;
-  }
-
-  /**
-   * Count number of children of a certain type of the given element.
-   *
-   * @param elem the element whose kids are to be counted
-   * @param nodeType DOCUMENTME
-   *
-   * @return the number of matching kids.
-   */
-  public static int countKids(Element elem, short nodeType) {
-    int nkids = 0;
-    for (Node n = elem.getFirstChild(); n != null; n = n.getNextSibling()) {
-      if (n.getNodeType() == nodeType) {
-        nkids++;
-      }
-    }
-    return nkids;
-  }
-
-
-
-  /**
-   * This method traverses the DOM and grabs namespace declarations
-   * on parent elements with the intent of preserving them for children.  <em>Note
-   * that the DOM level 3 document method {@link Element#getAttribute(java.lang.String)}
-   * is not desirable in this case, as it does not respect namespace prefix
-   * bindings that may affect attribute values.  (Namespaces in DOM are
-   * uncategorically a mess, especially in the context of XML Schema.)</em>
-   * @param el the starting element
-   * @return a {@link Map} containing prefix bindings.
-   */
-  public static Map<String, String> getParentNamespaces(Element el) {
-    HashMap<String,String> pref = new HashMap<String,String>();
-    Map mine = getMyNamespaces(el);
-    Node n = el.getParentNode();
-    do {
-      if (n instanceof Element) {
-        Element l = (Element) n;
-        NamedNodeMap nnm = l.getAttributes();
+    /**
+     * Returns the value of an attribute of an element. Returns null if the
+     * attribute is not found (whereas Element.getAttributeNS returns "" if an
+     * attrib is not found).
+     *
+     * @param el Element whose attrib is looked for
+     * @param namespaceURI namespace URI of attribute to look for
+     * @param localPart local part of attribute to look for
+     *
+     * @return the attribute value
+     */
+    static public String getAttributeNS(Element el, String namespaceURI,
+                                        String localPart) {
+        String sRet = null;
+        Attr attr = el.getAttributeNodeNS(namespaceURI, localPart);
+        if (attr != null) {
+            sRet = attr.getValue();
+        }
+        return sRet;
+    }
+
+    /**
+     * Concat all the text and cdata node children of this elem and return the
+     * resulting text.
+     *
+     * @param parentEl the element whose cdata/text node values are to be
+     *        combined.
+     *
+     * @return the concatanated string.
+     */
+    static public String getChildCharacterData(Element parentEl) {
+        if (parentEl == null) { return null; }
+        Node tempNode = parentEl.getFirstChild();
+        StringBuffer strBuf = new StringBuffer();
+        CharacterData charData;
+        while (tempNode != null) {
+            switch (tempNode.getNodeType()) {
+                case Node.TEXT_NODE:
+                case Node.CDATA_SECTION_NODE:
+                    charData = (CharacterData) tempNode;
+                    strBuf.append(charData.getData());
+                    break;
+            }
+            tempNode = tempNode.getNextSibling();
+        }
+        return strBuf.toString();
+    }
+
+    /**
+     * DOCUMENTME
+     *
+     * @param el DOCUMENTME
+     * @param id DOCUMENTME
+     *
+     * @return DOCUMENTME
+     */
+    public static Element getElementByID(Element el, String id) {
+        if (el == null) { return null; }
+        String thisId = el.getAttribute("id");
+        if (id.equals(thisId)) { return el; }
+        NodeList list = el.getChildNodes();
+        for (int i = 0; i < list.getLength(); i++) {
+            Node node = list.item(i);
+            if (node instanceof Element) {
+                Element ret = getElementByID((Element) node, id);
+                if (ret != null) { return ret; }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Return the first child element of the given element. Null if no children
+     * are found.
+     *
+     * @param elem Element whose child is to be returned
+     *
+     * @return the first child element.
+     */
+    public static Element getFirstChildElement(Element elem) {
+        if (elem == null)
+            throw new NullPointerException("elem parameter must not be null!");
+
+        for (Node n = elem.getFirstChild(); n != null; n = n.getNextSibling()) {
+            if (n.getNodeType() == Node.ELEMENT_NODE) { return (Element) n; }
+        }
+        return null;
+    }
+
+    /**
+     * Given a prefix and a node, return the namespace URI that the prefix has
+     * been associated with. This method is useful in resolving the namespace
+     * URI of attribute values which are being interpreted as QNames. If prefix
+     * is null, this method will return the default namespace.
+     *
+     * @param context the starting node (looks up recursively from here)
+     * @param prefix the prefix to find an xmlns:prefix=uri for
+     *
+     * @return the namespace URI or null if not found
+     */
+    public static String getNamespaceURIFromPrefix(Node context, String prefix) {
+        short nodeType = context.getNodeType();
+        Node tempNode = null;
+        switch (nodeType) {
+            case Node.ATTRIBUTE_NODE: {
+                tempNode = ((Attr) context).getOwnerElement();
+                break;
+            }
+            case Node.ELEMENT_NODE: {
+                tempNode = context;
+                break;
+            }
+            default: {
+                tempNode = context.getParentNode();
+                break;
+            }
+        }
+        while ((tempNode != null) && (tempNode.getNodeType() == Node.ELEMENT_NODE)) {
+            Element tempEl = (Element) tempNode;
+            String namespaceURI = (prefix == null) ? getAttribute(tempEl, "xmlns")
+                    : getAttributeNS(tempEl, NS_URI_XMLNS, prefix);
+            if (namespaceURI != null) {
+                return namespaceURI;
+            }
+            tempNode = tempEl.getParentNode();
+        }
+        return null;
+    }
+
+    /**
+     * Return the next sibling element of the given element. Null if no more
+     * sibling elements are found.
+     *
+     * @param elem Element whose sibling element is to be returned
+     *
+     * @return the next sibling element.
+     */
+    public static Element getNextSiblingElement(Element elem) {
+        for (Node n = elem.getNextSibling(); n != null; n = n.getNextSibling()) {
+            if (n.getNodeType() == Node.ELEMENT_NODE) { return (Element) n; }
+        }
+        return null;
+    }
+
+    /**
+     * DOCUMENTME
+     *
+     * @param el DOCUMENTME
+     * @param attrName DOCUMENTME
+     *
+     * @return DOCUMENTME
+     *
+     * @throws IllegalArgumentException DOCUMENTME
+     */
+    public static QName getQualifiedAttributeValue(Element el, String attrName)
+            throws IllegalArgumentException {
+        String attrValue = DOMUtils.getAttribute(el, attrName);
+        if (attrValue != null) {
+            int index = attrValue.indexOf(':');
+            String attrValuePrefix = (index != -1) ? attrValue.substring(0, index)
+                    : null;
+            String attrValueLocalPart = attrValue.substring(index + 1);
+            String attrValueNamespaceURI = DOMUtils.getNamespaceURIFromPrefix(el,
+                    attrValuePrefix);
+            if (attrValueNamespaceURI != null) {
+                return new QName(attrValueNamespaceURI, attrValueLocalPart);
+            }
+            throw new IllegalArgumentException("Unable to determine "
+                    + "namespace of '"
+                    + ((attrValuePrefix != null) ? (attrValuePrefix + ":") : "")
+                    + attrValueLocalPart + "'.");
+        }
+        return null;
+    }
+
+    /**
+     * Count number of children of a certain type of the given element.
+     *
+     * @param elem the element whose kids are to be counted
+     * @param nodeType DOCUMENTME
+     *
+     * @return the number of matching kids.
+     */
+    public static int countKids(Element elem, short nodeType) {
+        int nkids = 0;
+        for (Node n = elem.getFirstChild(); n != null; n = n.getNextSibling()) {
+            if (n.getNodeType() == nodeType) {
+                nkids++;
+            }
+        }
+        return nkids;
+    }
+
+
+
+    /**
+     * This method traverses the DOM and grabs namespace declarations
+     * on parent elements with the intent of preserving them for children.  <em>Note
+     * that the DOM level 3 document method {@link Element#getAttribute(java.lang.String)}
+     * is not desirable in this case, as it does not respect namespace prefix
+     * bindings that may affect attribute values.  (Namespaces in DOM are
+     * uncategorically a mess, especially in the context of XML Schema.)</em>
+     * @param el the starting element
+     * @return a {@link Map} containing prefix bindings.
+     */
+    public static Map<String, String> getParentNamespaces(Element el) {
+        HashMap<String,String> pref = new HashMap<String,String>();
+        Map mine = getMyNamespaces(el);
+        Node n = el.getParentNode();
+        do {
+            if (n instanceof Element) {
+                Element l = (Element) n;
+                NamedNodeMap nnm = l.getAttributes();
+                int len = nnm.getLength();
+                for (int i = 0; i < len; ++i) {
+                    Attr a = (Attr) nnm.item(i);
+                    if (isNSAttribute(a)) {
+                        String key = getNSPrefixFromNSAttr(a);
+                        String uri = a.getValue();
+                        // prefer prefix bindings that are lower down in the tree.
+                        if (pref.containsKey(key) || mine.containsKey(key)) continue;
+                        pref.put(key, uri);
+                    }
+                }
+            }
+            n = n.getParentNode();
+        } while (n != null && n.getNodeType() != Node.DOCUMENT_NODE);
+        return pref;
+    }
+
+    /**
+     * Construct a {@link NSContext} instance for the supplied element.
+     * @param el the <code>Element</code> to gather the namespace context for
+     * @return the <code>NSContext</code>
+     */
+    public static NSContext getMyNSContext(Element el) {
+        NSContext ns = new NSContext();
+        ns.register(getParentNamespaces(el));
+        ns.register(getMyNamespaces(el));
+        return ns;
+    }
+
+    public static Map<String,String> getMyNamespaces(Element el) {
+        HashMap<String,String> mine = new HashMap<String,String>();
+        NamedNodeMap nnm = el.getAttributes();
         int len = nnm.getLength();
-        for (int i = 0; i < len; ++i) {
-          Attr a = (Attr) nnm.item(i);
-          if (isNSAttribute(a)) {
-            String key = getNSPrefixFromNSAttr(a);            
-            String uri = a.getValue();
-            // prefer prefix bindings that are lower down in the tree.
-            if (pref.containsKey(key) || mine.containsKey(key)) continue;
-            pref.put(key, uri);
-          }
-        }
-      }
-      n = n.getParentNode();
-    } while (n != null && n.getNodeType() != Node.DOCUMENT_NODE);
-    return pref;
-  }
-
-  /**
-   * Construct a {@link NSContext} instance for the supplied element.
-   * @param el the <code>Element</code> to gather the namespace context for
-   * @return the <code>NSContext</code>
-   */
-  public static NSContext getMyNSContext(Element el) {
-    NSContext ns = new NSContext();
-    ns.register(getParentNamespaces(el));
-    ns.register(getMyNamespaces(el));
-    return ns;
-  }
-  
-  public static Map<String,String> getMyNamespaces(Element el) {
-    HashMap<String,String> mine = new HashMap<String,String>();
-    NamedNodeMap nnm = el.getAttributes();
-    int len = nnm.getLength();
-    for (int i=0; i < len; ++i) {
-      Attr a = (Attr) nnm.item(i);
-      if (isNSAttribute(a)) {
-        mine.put(getNSPrefixFromNSAttr(a),a.getValue());
-      }
-    }
-    return mine;
-  }
-  
-  /**
-   * Test whether an attribute contains a namespace declaration. 
-   * @param a an {@link Attr} to test.
-   * @return <code>true</code> if the {@link Attr} is a namespace declaration
-   */
-  public static boolean isNSAttribute(Attr a) {
-    assert a != null;
-    String s = a.getNamespaceURI();
-    return (s != null && s.equals(NS_URI_XMLNS));
-  }
-
-  /**
-   * Fetch the non-null namespace prefix from a {@link Attr} that declares
-   * a namespace.  (The DOM APIs will return <code>null</code> for a non-prefixed
-   * declaration.
-   * @param a the {@link Attr} with the declaration (must be non-<code>null</code).
-   * @return the namespace prefix or <code>&quot;&quot;</code> if none was
-   * declared, e.g., <code>xmlns=&quot;foo&quot;</code>.
-   */
-  public static String getNSPrefixFromNSAttr(Attr a) {
-    assert a != null;
-    assert isNSAttribute(a);
-    if (a.getPrefix() == null) {
-      return "";
-    }
-    return a.getName().substring(a.getPrefix().length()+1);
-  }
-
-    /**
-   * Convert a DOM node to a stringified XML representation.
-   */
-  static public String domToString(Node node) {
-    if (node == null) {
-      throw new IllegalArgumentException("Cannot stringify null Node!");
-    }
-
-    String value = null;
-    short nodeType = node.getNodeType();
-    if (nodeType == Node.ELEMENT_NODE || nodeType == Node.DOCUMENT_NODE) {
-      // serializer doesn't handle Node type well, only Element
-      DOMSerializerImpl ser = new DOMSerializerImpl();
-      ser.setParameter(Constants.DOM_NAMESPACES, Boolean.TRUE);
-      ser.setParameter(Constants.DOM_WELLFORMED, Boolean.FALSE );
-      ser.setParameter(Constants.DOM_VALIDATE, Boolean.FALSE);
-
-      // create a proper XML encoding header based on the input document;
-      // default to UTF-8 if the parent document's encoding is not accessible
-      String usedEncoding = "UTF-8";
-      Document parent = node.getOwnerDocument();
-      if (parent != null) {
-        String parentEncoding = parent.getXmlEncoding();
-        if (parentEncoding != null) {
-          usedEncoding = parentEncoding;
-        }
-      }
-
-      // the receiver of the DOM
-      DOMOutputImpl out = new DOMOutputImpl();
-      out.setEncoding(usedEncoding);
-
-      // we write into a String
-      StringWriter writer = new StringWriter(4096);
-      out.setCharacterStream(writer);
-
-      // out, ye characters!
-      ser.write(node, out);
-      writer.flush();
-
-      // finally get the String
-      value = writer.toString();
-    } else {
-      value = node.getNodeValue();
-    }
-    return value;
-  }
-
-  public static void serialize(Element elmt, OutputStream ostr) {
-    String usedEncoding = "UTF-8";
-    Document parent = elmt.getOwnerDocument();
-    if (parent != null) {
-      String parentEncoding = parent.getXmlEncoding();
-      if (parentEncoding != null) {
-        usedEncoding = parentEncoding;
-      }
-    }
-
-    DOMOutputImpl out = new DOMOutputImpl();
-    out.setEncoding(usedEncoding);
-
-    DOMSerializerImpl ser = new DOMSerializerImpl();
-    out.setByteStream(ostr);
-    ser.write(elmt, out);
-  }
-
-  /**
-   * Convert a DOM node to a stringified XML representation.
-   */
-  static public String domToStringLevel2(Node node) {
-    if (node == null) {
-      throw new IllegalArgumentException("Cannot stringify null Node!");
-    }
-
-    String value = null;
-    short nodeType = node.getNodeType();
-    if (nodeType == Node.ELEMENT_NODE || nodeType == Node.DOCUMENT_NODE) {
-      // serializer doesn't handle Node type well, only Element
-      DOMSerializerImpl ser = new DOMSerializerImpl();
-      ser.setParameter(Constants.DOM_NAMESPACES, Boolean.TRUE);
-      ser.setParameter(Constants.DOM_WELLFORMED, Boolean.FALSE );
-      ser.setParameter(Constants.DOM_VALIDATE, Boolean.FALSE);
-
-      // the receiver of the DOM
-      DOMOutputImpl out = new DOMOutputImpl();
-      out.setEncoding("UTF-8");
-
-      // we write into a String
-      StringWriter writer = new StringWriter(4096);
-      out.setCharacterStream(writer);
-
-      // out, ye characters!
-      ser.write(node, out);
-      writer.flush();
-
-      // finally get the String
-      value = writer.toString();
-    } else {
-      value = node.getNodeValue();
-    }
-    return value;
-  }
-
-  /**
-   * Return the first child element of the given element which has the given
-   * attribute with the given value.
-   *
-   * @param elem the element whose children are to be searched
-   * @param attrName the attrib that must be present
-   * @param attrValue the desired value of the attribute
-   *
-   * @return the first matching child element.
-   */
-  public static Element findChildElementWithAttribute(Element elem,
-      String attrName, String attrValue) {
-    for (Node n = elem.getFirstChild(); n != null; n = n.getNextSibling()) {
-      if (n.getNodeType() == Node.ELEMENT_NODE) {
-        if (attrValue.equals(DOMUtils.getAttribute((Element) n, attrName))) { return (Element) n; }
-      }
-    }
-    return null;
-  }
-
-  /**
-   * Parse a String into a DOM.
-   *
-   * @param s DOCUMENTME
-   *
-   * @return DOCUMENTME
-   *
-   * @throws SAXException DOCUMENTME
-   * @throws IOException DOCUMENTME
-   */
-  static public Element stringToDOM(String s) throws SAXException, IOException {
-    return parse(new InputSource(new StringReader(s))).getDocumentElement();
-  }
-
-  /**
-   * Perform a naive check to see if a document is a WSDL document
-   * based on the root element name and namespace URI.
-   * @param d the {@link Document} to check
-   * @return <code>true</code> if the root element appears correct
-   */
-  public static boolean isWsdlDocument(Document d) {
-    Element e = d.getDocumentElement();
-    String uri = e.getNamespaceURI();
-    String localName = e.getLocalName();
-    if (uri == null || localName == null) { return false; }
-    return uri.equals(WSDL_NS) && localName.equals(WSDL_ROOT_ELEMENT);
-  }
-
-  /**
-   * Perform a naive check to see if a document is an XML schema document
-   * based on the root element name and namespace URI.
-   * @param d the {@link Document} to check
-   * @return <code>true</code> if the root element appears correct
-   */
-  public static boolean isXmlSchemaDocument(Document d) {
-    Element e = d.getDocumentElement();
-    String uri = e.getNamespaceURI();
-    String localName = e.getLocalName();
-    if (uri == null || localName == null) { return false; }
-    return uri.equals(XSD_NS) && localName.equals(XSD_ROOT_ELEMENT);
-  }
-
-  public static final String WSDL_NS = "http://schemas.xmlsoap.org/wsdl/";
-  public static final String WSDL_ROOT_ELEMENT = "definitions";
-  public static final String XSD_NS = "http://www.w3.org/2001/XMLSchema";
-  public static final String XSD_ROOT_ELEMENT = "schema";
-
-  /**
-   * @param el
-   */
-  public static void pancakeNamespaces(Element el) {
-    Map ns = getParentNamespaces(el);
-    Document d = el.getOwnerDocument();
-    assert d != null;
-    Iterator it = ns.keySet().iterator();
-    while (it.hasNext()) {
-      String key = (String) it.next();
-      String uri = (String) ns.get(key);
-      Attr a = d.createAttributeNS(NS_URI_XMLNS,
-          (key.length() != 0)?("xmlns:" + key):("xmlns"));
-      a.setValue(uri);
-      el.setAttributeNodeNS(a);
-    }
-  }
-
-  public static Document newDocument() {
-    DocumentBuilder db;
-    try {
-      db = borrow();
-    } catch (Exception ex) {
-      throw new RuntimeException("XML PARSE ERROR (NO PARSERS!)", ex);
-    }
-    try {
-      return db.newDocument();
-    } finally {
-      returnObject(db);
-    }
-  }
-
-  /**
-   * Parse an XML stream using the pooled document builder.
-   * @param inputStream input stream
-   * @return parsed XML document
-   */
-  public static Document parse(InputStream inputStream) throws SAXException, IOException {
-    return parse(new InputSource(inputStream));
-  }
-
-  /**
-   * Parse an XML document located using an {@link InputSource} using the
-   * pooled document builder.
-   */
-  public static Document parse(InputSource inputSource) throws SAXException,IOException{
-    DocumentBuilder db = borrow();
-    try {
-      return db.parse(inputSource);
-    } finally {
-      returnObject(db);
-    }
-
-  }
-
-  /**
-   * Borrow a {@link DocumentBuilder} to the pool.
-   */
-  private static synchronized DocumentBuilder borrow() throws SAXException {
-    try {
-      return (DocumentBuilder) __documentBuilderPool.borrowObject();
-    } catch (SAXException sae) {
-      throw sae;
-    } catch (Exception ex) {
-      throw new SAXException(ex);
-    }
-
-  }
-
-  /** Return the {@link DocumentBuilder} to the pool. */
-  private static synchronized void returnObject(DocumentBuilder db) {
-    try {
-      __documentBuilderPool.returnObject(db);
-    } catch (Exception ex) {
-      __log.debug("Error returning DocumentBuilder to object pool (ignoring).", ex);
-    }
-  }
-
-  /**
-   * Check that an element is empty, i.e., it contains no non-whitespace text or 
-   * elements as children.
-   * @param el the element
-   * @return <code>true</code> if the element is empty, <code>false</code> if not.
-   */
-  public static boolean isEmptyElement(Element el) {
-    NodeList nl = el.getChildNodes();
-    int len = nl.getLength();
-    for (int i=0; i < len; ++i) {
-      switch (nl.item(i).getNodeType()) {
-        case Node.CDATA_SECTION_NODE:
-        case Node.TEXT_NODE:
-          String s = nl.item(i).getNodeValue();
-          if (s != null && s.trim().length() > 0) {
-            return false;
-          }
-          break;
-        case Node.ELEMENT_NODE:
-          return false;
-      }
-    }
-    return true;
-  }
-
-  /**
-   * @param el
-   * @return
-   */
-  public static QName getElementQName(Element el) {
-    return new QName(el.getNamespaceURI(),el.getLocalName());
-  }
-
-  /**
-   * Remove the child nodes under another node.
-   * @param target the <code>Node</code> to remove the children from.
-   */
-  public static void removeChildren(Node target) {
-    while (target.hasChildNodes()) {
-      target.removeChild(target.getFirstChild());
-    }
-  }
-
-  /**
-   * Drop the attributes from an element, except possibly an <code>xmlns</code>
-   * attribute that declares its namespace.
-   * @param target the element whose attributes will be removed.
-   * @param flag preserve namespace declaration
-   */
-  public static void removeAttributes(Element target, boolean flag) {
-    if (!target.hasAttributes()) {
-      return;
-    }
-    String prefix = target.getPrefix();
-    NamedNodeMap nnm = target.getAttributes();
-    Attr toPutBack = null;
-    if (flag) {
-      if (prefix== null) {
-        toPutBack = target.getAttributeNodeNS(NS_URI_XMLNS,"xmlns");
-      } else {
-        toPutBack = target.getAttributeNodeNS(NS_URI_XMLNS,"xmlns:" + prefix);
-      }
-      
-    }
-    while(nnm.getLength() != 0) {
-      target.removeAttributeNode((Attr) nnm.item(0));
-    }
-    if (toPutBack != null) {
-      target.setAttributeNodeNS(toPutBack);
-    }
-  }
-  
-  public static Element findChildByName(Element parent, QName name) {
-  	return findChildByName(parent, name, false);
-  }
-
-  public static Element findChildByName(Element parent, QName name, boolean recurse) {
-    if (parent == null)
-      throw new IllegalArgumentException("null parent");
-    if (name == null)
-      throw new IllegalArgumentException("null name");
-
-    NodeList nl = parent.getChildNodes();
-    for (int i = 0; i < nl.getLength(); ++i) {
-      Node c = nl.item(i);
-      if(c.getNodeType() != Node.ELEMENT_NODE)
-        continue;
-      if (new QName(c.getNamespaceURI(),c.getLocalName()).equals(name))
-        return (Element) c;
-    }
-    
-    if(recurse){
-      NodeList cnl = parent.getChildNodes();
-      for (int i = 0; i < cnl.getLength(); ++i) {
-        Node c = cnl.item(i);
-        if(c.getNodeType() != Node.ELEMENT_NODE)
-          continue;
-        Element result = findChildByName((Element)c, name, recurse);
-        if(result != null)
-          return result;
-      }
-    }
-    return null;
-  }
-
-  public static String getTextContent(Node node) {
-    for (int m = 0; m < node.getChildNodes().getLength(); m++) {
-      Node child = node.getChildNodes().item(m);
-      if (child.getNodeType() == Node.TEXT_NODE) {
-        String childText = child.getNodeValue().trim();
-        if (childText.length() > 0) return childText;
-      }
-    }
-    return null;
-  }
-
-  public static Element getElementContent(Node node) {
-    for (int m = 0; m < node.getChildNodes().getLength(); m++) {
-      Node child = node.getChildNodes().item(m);
-      if (child.getNodeType() == Node.ELEMENT_NODE) return (Element) child;
+        for (int i=0; i < len; ++i) {
+            Attr a = (Attr) nnm.item(i);
+            if (isNSAttribute(a)) {
+                mine.put(getNSPrefixFromNSAttr(a),a.getValue());
+            }
+        }
+        return mine;
+    }
+
+    /**
+     * Test whether an attribute contains a namespace declaration.
+     * @param a an {@link Attr} to test.
+     * @return <code>true</code> if the {@link Attr} is a namespace declaration
+     */
+    public static boolean isNSAttribute(Attr a) {
+        assert a != null;
+        String s = a.getNamespaceURI();
+        return (s != null && s.equals(NS_URI_XMLNS));
+    }
+
+    /**
+     * Fetch the non-null namespace prefix from a {@link Attr} that declares
+     * a namespace.  (The DOM APIs will return <code>null</code> for a non-prefixed
+     * declaration.
+     * @param a the {@link Attr} with the declaration (must be non-<code>null</code).
+     * @return the namespace prefix or <code>&quot;&quot;</code> if none was
+     * declared, e.g., <code>xmlns=&quot;foo&quot;</code>.
+     */
+    public static String getNSPrefixFromNSAttr(Attr a) {
+        assert a != null;
+        assert isNSAttribute(a);
+        if (a.getPrefix() == null) {
+            return "";
+        }
+        return a.getName().substring(a.getPrefix().length()+1);
+    }
+
+    /**
+     * Convert a DOM node to a stringified XML representation.
+     */
+    static public String domToString(Node node) {
+        if (node == null) {
+            throw new IllegalArgumentException("Cannot stringify null Node!");
+        }
+
+        String value = null;
+        short nodeType = node.getNodeType();
+        if (nodeType == Node.ELEMENT_NODE || nodeType == Node.DOCUMENT_NODE) {
+            // serializer doesn't handle Node type well, only Element
+            DOMSerializerImpl ser = new DOMSerializerImpl();
+            ser.setParameter(Constants.DOM_NAMESPACES, Boolean.TRUE);
+            ser.setParameter(Constants.DOM_WELLFORMED, Boolean.FALSE );
+            ser.setParameter(Constants.DOM_VALIDATE, Boolean.FALSE);
+
+            // create a proper XML encoding header based on the input document;
+            // default to UTF-8 if the parent document's encoding is not accessible
+            String usedEncoding = "UTF-8";
+            Document parent = node.getOwnerDocument();
+            if (parent != null) {
+                String parentEncoding = parent.getXmlEncoding();
+                if (parentEncoding != null) {
+                    usedEncoding = parentEncoding;
+                }
+            }
+
+            // the receiver of the DOM
+            DOMOutputImpl out = new DOMOutputImpl();
+            out.setEncoding(usedEncoding);
+
+            // we write into a String
+            StringWriter writer = new StringWriter(4096);
+            out.setCharacterStream(writer);
+
+            // out, ye characters!
+            ser.write(node, out);
+            writer.flush();
+
+            // finally get the String
+            value = writer.toString();
+        } else {
+            value = node.getNodeValue();
+        }
+        return value;
+    }
+
+    public static void serialize(Element elmt, OutputStream ostr) {
+        String usedEncoding = "UTF-8";
+        Document parent = elmt.getOwnerDocument();
+        if (parent != null) {
+            String parentEncoding = parent.getXmlEncoding();
+            if (parentEncoding != null) {
+                usedEncoding = parentEncoding;
+            }
+        }
+
+        DOMOutputImpl out = new DOMOutputImpl();
+        out.setEncoding(usedEncoding);
+
+        DOMSerializerImpl ser = new DOMSerializerImpl();
+        out.setByteStream(ostr);
+        ser.write(elmt, out);
+    }
+
+    /**
+     * Convert a DOM node to a stringified XML representation.
+     */
+    static public String domToStringLevel2(Node node) {
+        if (node == null) {
+            throw new IllegalArgumentException("Cannot stringify null Node!");
+        }
+
+        String value = null;
+        short nodeType = node.getNodeType();
+        if (nodeType == Node.ELEMENT_NODE || nodeType == Node.DOCUMENT_NODE) {
+            // serializer doesn't handle Node type well, only Element
+            DOMSerializerImpl ser = new DOMSerializerImpl();
+            ser.setParameter(Constants.DOM_NAMESPACES, Boolean.TRUE);
+            ser.setParameter(Constants.DOM_WELLFORMED, Boolean.FALSE );
+            ser.setParameter(Constants.DOM_VALIDATE, Boolean.FALSE);
+
+            // the receiver of the DOM
+            DOMOutputImpl out = new DOMOutputImpl();
+            out.setEncoding("UTF-8");
+
+            // we write into a String
+            StringWriter writer = new StringWriter(4096);
+            out.setCharacterStream(writer);
+
+            // out, ye characters!
+            ser.write(node, out);
+            writer.flush();
+
+            // finally get the String
+            value = writer.toString();
+        } else {
+            value = node.getNodeValue();
+        }
+        return value;
+    }
+
+    /**
+     * Return the first child element of the given element which has the given
+     * attribute with the given value.
+     *
+     * @param elem the element whose children are to be searched
+     * @param attrName the attrib that must be present
+     * @param attrValue the desired value of the attribute
+     *
+     * @return the first matching child element.
+     */
+    public static Element findChildElementWithAttribute(Element elem,
+                                                        String attrName, String attrValue) {
+        for (Node n = elem.getFirstChild(); n != null; n = n.getNextSibling()) {
+            if (n.getNodeType() == Node.ELEMENT_NODE) {
+                if (attrValue.equals(DOMUtils.getAttribute((Element) n, attrName))) { return (Element) n; }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Parse a String into a DOM.
+     *
+     * @param s DOCUMENTME
+     *
+     * @return DOCUMENTME
+     *
+     * @throws SAXException DOCUMENTME
+     * @throws IOException DOCUMENTME
+     */
+    static public Element stringToDOM(String s) throws SAXException, IOException {
+        return parse(new InputSource(new StringReader(s))).getDocumentElement();
+    }
+
+    /**
+     * Perform a naive check to see if a document is a WSDL document
+     * based on the root element name and namespace URI.
+     * @param d the {@link Document} to check
+     * @return <code>true</code> if the root element appears correct
+     */
+    public static boolean isWsdlDocument(Document d) {
+        Element e = d.getDocumentElement();
+        String uri = e.getNamespaceURI();
+        String localName = e.getLocalName();
+        if (uri == null || localName == null) { return false; }
+        return uri.equals(WSDL_NS) && localName.equals(WSDL_ROOT_ELEMENT);
+    }
+
+    /**
+     * Perform a naive check to see if a document is an XML schema document
+     * based on the root element name and namespace URI.
+     * @param d the {@link Document} to check
+     * @return <code>true</code> if the root element appears correct
+     */
+    public static boolean isXmlSchemaDocument(Document d) {
+        Element e = d.getDocumentElement();
+        String uri = e.getNamespaceURI();
+        String localName = e.getLocalName();
+        if (uri == null || localName == null) { return false; }
+        return uri.equals(XSD_NS) && localName.equals(XSD_ROOT_ELEMENT);
+    }
+
+    public static final String WSDL_NS = "http://schemas.xmlsoap.org/wsdl/";
+    public static final String WSDL_ROOT_ELEMENT = "definitions";
+    public static final String XSD_NS = "http://www.w3.org/2001/XMLSchema";
+    public static final String XSD_ROOT_ELEMENT = "schema";
+
+    /**
+     * @param el
+     */
+    public static void pancakeNamespaces(Element el) {
+        Map ns = getParentNamespaces(el);
+        Document d = el.getOwnerDocument();
+        assert d != null;
+        Iterator it = ns.keySet().iterator();
+        while (it.hasNext()) {
+            String key = (String) it.next();
+            String uri = (String) ns.get(key);
+            Attr a = d.createAttributeNS(NS_URI_XMLNS,
+                    (key.length() != 0)?("xmlns:" + key):("xmlns"));
+            a.setValue(uri);
+            el.setAttributeNodeNS(a);
+        }
+    }
+
+    public static Document newDocument() {
+        DocumentBuilder db;
+        try {
+            db = borrow();
+        } catch (Exception ex) {
+            throw new RuntimeException("XML PARSE ERROR (NO PARSERS!)", ex);
+        }
+        try {
+            return db.newDocument();
+        } finally {
+            returnObject(db);
+        }
+    }
+
+    /**
+     * Parse an XML stream using the pooled document builder.
+     * @param inputStream input stream
+     * @return parsed XML document
+     */
+    public static Document parse(InputStream inputStream) throws SAXException, IOException {
+        return parse(new InputSource(inputStream));
+    }
+
+    /**
+     * Parse an XML document located using an {@link InputSource} using the
+     * pooled document builder.
+     */
+    public static Document parse(InputSource inputSource) throws SAXException,IOException{
+        DocumentBuilder db = borrow();
+        try {
+            return db.parse(inputSource);
+        } finally {
+            returnObject(db);
+        }
+
+    }
+
+    /**
+     * Borrow a {@link DocumentBuilder} to the pool.
+     */
+    private static synchronized DocumentBuilder borrow() throws SAXException {
+        try {
+            return (DocumentBuilder) __documentBuilderPool.borrowObject();
+        } catch (SAXException sae) {
+            throw sae;
+        } catch (Exception ex) {
+            throw new SAXException(ex);
+        }
+
+    }
+
+    /** Return the {@link DocumentBuilder} to the pool. */
+    private static synchronized void returnObject(DocumentBuilder db) {
+        try {
+            __documentBuilderPool.returnObject(db);
+        } catch (Exception ex) {
+            __log.debug("Error returning DocumentBuilder to object pool (ignoring).", ex);
+        }
+    }
+
+    /**
+     * Check that an element is empty, i.e., it contains no non-whitespace text or
+     * elements as children.
+     * @param el the element
+     * @return <code>true</code> if the element is empty, <code>false</code> if not.
+     */
+    public static boolean isEmptyElement(Element el) {
+        NodeList nl = el.getChildNodes();
+        int len = nl.getLength();
+        for (int i=0; i < len; ++i) {
+            switch (nl.item(i).getNodeType()) {
+                case Node.CDATA_SECTION_NODE:
+                case Node.TEXT_NODE:
+                    String s = nl.item(i).getNodeValue();
+                    if (s != null && s.trim().length() > 0) {
+                        return false;
+                    }
+                    break;
+                case Node.ELEMENT_NODE:
+                    return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * @param el
+     * @return
+     */
+    public static QName getElementQName(Element el) {
+        return new QName(el.getNamespaceURI(),el.getLocalName());
+    }
+
+    /**
+     * Remove the child nodes under another node.
+     * @param target the <code>Node</code> to remove the children from.
+     */
+    public static void removeChildren(Node target) {
+        while (target.hasChildNodes()) {
+            target.removeChild(target.getFirstChild());
+        }
+    }
+
+    /**
+     * Drop the attributes from an element, except possibly an <code>xmlns</code>
+     * attribute that declares its namespace.
+     * @param target the element whose attributes will be removed.
+     * @param flag preserve namespace declaration
+     */
+    public static void removeAttributes(Element target, boolean flag) {
+        if (!target.hasAttributes()) {
+            return;
+        }
+        String prefix = target.getPrefix();
+        NamedNodeMap nnm = target.getAttributes();
+        Attr toPutBack = null;
+        if (flag) {
+            if (prefix== null) {
+                toPutBack = target.getAttributeNodeNS(NS_URI_XMLNS,"xmlns");
+            } else {
+                toPutBack = target.getAttributeNodeNS(NS_URI_XMLNS,"xmlns:" + prefix);
+            }
+
+        }
+        while(nnm.getLength() != 0) {
+            target.removeAttributeNode((Attr) nnm.item(0));
+        }
+        if (toPutBack != null) {
+            target.setAttributeNodeNS(toPutBack);
+        }
+    }
+
+    public static Element findChildByName(Element parent, QName name) {
+        return findChildByName(parent, name, false);
+    }
+
+    public static Element findChildByName(Element parent, QName name, boolean recurse) {
+        if (parent == null)
+            throw new IllegalArgumentException("null parent");
+        if (name == null)
+            throw new IllegalArgumentException("null name");
+
+        NodeList nl = parent.getChildNodes();
+        for (int i = 0; i < nl.getLength(); ++i) {
+            Node c = nl.item(i);
+            if(c.getNodeType() != Node.ELEMENT_NODE)
+                continue;
+            // For a reason that I can't fathom, when using in-mem DAO we actually get elements with
+            // no localname.
+            String nodeName = c.getLocalName() != null ? c.getLocalName() : c.getNodeName();
+            if (new QName(c.getNamespaceURI(),nodeName).equals(name))
+                return (Element) c;
+        }
+
+        if(recurse){
+            NodeList cnl = parent.getChildNodes();
+            for (int i = 0; i < cnl.getLength(); ++i) {
+                Node c = cnl.item(i);
+                if(c.getNodeType() != Node.ELEMENT_NODE)
+                    continue;
+                Element result = findChildByName((Element)c, name, recurse);
+                if(result != null)
+                    return result;
+            }
+        }
+        return null;
+    }
+
+    public static String getTextContent(Node node) {
+        for (int m = 0; m < node.getChildNodes().getLength(); m++) {
+            Node child = node.getChildNodes().item(m);
+            if (child.getNodeType() == Node.TEXT_NODE) {
+                String childText = child.getNodeValue().trim();
+                if (childText.length() > 0) return childText;
+            }
+        }
+        return null;
+    }
+
+    public static Element getElementContent(Node node) {
+        for (int m = 0; m < node.getChildNodes().getLength(); m++) {
+            Node child = node.getChildNodes().item(m);
+            if (child.getNodeType() == Node.ELEMENT_NODE) return (Element) child;
+        }
+        return null;
     }
-    return null;
-  }
 
 }