Package de.danet.an.workflow.ejbs.client

Source Code of de.danet.an.workflow.ejbs.client.StandardWorkflowService$EventSubscriberImpl

/*
* This file is part of the WfMOpen project.
* Copyright (C) 2001-2003 Danet GmbH (www.danet.de), GS-AN.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
* $Id: StandardWorkflowService.java 2930 2009-02-16 16:20:07Z drmlipp $
*
* $Log$
* Revision 1.14  2007/10/07 18:40:10  mlipp
* Removed superfluous imports.
*
* Revision 1.13  2007/02/27 14:34:20  drmlipp
* Some refactoring to reduce cyclic dependencies.
*
* Revision 1.12  2007/02/21 21:32:29  mlipp
* Using pooled JMS connections when in EJB now.
*
* Revision 1.11  2007/02/17 21:22:56  mlipp
* Improved service caching and topic connection handling.
*
* Revision 1.10  2007/02/16 21:43:23  mlipp
* Improved.
*
* Revision 1.9  2007/02/15 14:28:29  drmlipp
* Even more improvements.
*
* Revision 1.8  2007/02/15 14:09:45  drmlipp
* Improved resource releasing.
*
* Revision 1.7  2007/02/15 13:52:37  drmlipp
* Fixed channel release problem.
*
* Revision 1.6  2006/09/29 12:32:09  drmlipp
* Consistently using WfMOpen as projct name now.
*
* Revision 1.5  2006/09/21 14:20:42  drmlipp
* New method for retrieving current user.
*
* Revision 1.4  2005/08/17 21:22:20  mlipp
* Removed deprecated method (as announced in 1.3).
*
* Revision 1.3  2005/08/17 21:15:31  mlipp
* Synchronized with 1.3.1p3.
*
* Revision 1.1.1.1.6.3  2005/08/17 20:39:12  drmlipp
* Removed usage of RAS on client side.
*
* Revision 1.2  2005/04/08 11:28:05  drmlipp
* Merged changes from 1.3 branch up to 1.3p6.
*
* Revision 1.1.1.1.6.2  2005/04/07 12:13:03  drmlipp
* Added event subscriber with filter.
*
* Revision 1.1.1.1.6.1  2005/04/06 15:42:06  drmlipp
* Added additional support for accessing the event queue to
* WorkflowService.
*
* Revision 1.1.1.1  2004/08/18 15:17:38  drmlipp
* Update to 1.2
*
* Revision 1.5  2004/07/11 19:56:51  lipp
* Adapted to JOnAS 4.1.2 naming scheme.
*
* Revision 1.4  2004/07/08 14:42:30  lipp
* Providing support for separated connection factories.
*
* Revision 1.3  2004/07/06 11:45:20  lipp
* Asure usability in various application servers.
*
* Revision 1.2  2004/06/14 19:37:20  lipp
* Fixed assignment functions and cleaned up assignment related
* interfaces.
*
* Revision 1.1  2004/02/21 21:31:00  lipp
* Some more refactoring to resolve cyclic dependencies.
*
* Revision 1.28  2004/02/12 13:10:38  lipp
* Renamed openChannel to getChannel (channels have no open state).
*
* Revision 1.27  2004/01/30 14:36:30  lipp
* Partial implementation of message receipt.
*
* Revision 1.26  2004/01/28 16:11:38  lipp
* Re-implementation of chabacc, Sender working.
*
* Revision 1.25  2004/01/23 12:49:26  lipp
* Fixes to WorkflowService[Factory] implementation/documentation.
*
* Revision 1.24  2004/01/22 16:10:50  lipp
* Channel message queue not available yet.
*
* Revision 1.23  2004/01/22 15:06:09  lipp
* Clarified serializability of workflow service.
*
* Revision 1.22  2003/11/21 14:53:50  lipp
* Create topic connection on client side, support initial context
* override.
*
* Revision 1.21  2003/10/06 15:20:27  lipp
* Made doFinish available in WorkflowService.
*
* Revision 1.20  2003/06/27 08:51:45  lipp
* Fixed copyright/license information.
*
* Revision 1.19  2003/06/01 20:58:50  lipp
* Moved toSAX to batch.
*
* Revision 1.18  2003/05/02 15:28:29  lipp
* Resolved some more package dependencies.
*
* Revision 1.17  2003/05/02 14:55:58  lipp
* Resolved some more package dependencies.
*
* Revision 1.16  2003/04/26 16:11:14  lipp
* Moved some classes to reduce package dependencies.
*
* Revision 1.15  2003/04/22 16:35:25  lipp
* Made SAXEventBuffer outer class.
*
* Revision 1.14  2003/03/31 16:50:28  huaiyang
* Logging using common-logging.
*
* Revision 1.13  2003/02/25 17:08:05  lipp
* Reorganized requester implementation.
*
* Revision 1.12  2003/02/11 08:50:41  lipp
* Updated comment.
*
* Revision 1.11  2003/02/07 15:56:19  lipp
* Implemented Requester notifications.
*
* Revision 1.10  2003/02/06 12:47:14  lipp
* Implemented Requester (no event handling yet).
*
* Revision 1.9  2003/02/05 15:57:06  lipp
* Replaced DummyRequester with DefaultRequester.
*
* Revision 1.8  2002/12/19 21:37:42  lipp
* Reorganized interfaces.
*
* Revision 1.7  2002/12/19 16:23:46  lipp
* Resolved illegal dependency between apis and danet.an.util.
*
* Revision 1.6  2002/12/10 11:21:05  lipp
* Added batch processing as "generic DTO".
*
* Revision 1.5  2002/11/22 09:56:15  lipp
* Clarified usage of the danet utility bean for user preferences.
*
* Revision 1.4  2002/09/19 14:37:37  lipp
* Using WorkflowService.release now and optimized process definition
* storage.
*
* Revision 1.3  2002/09/18 21:26:51  lipp
* Removed SAXFacade (integrated with WorkflowEngine).
*
* Revision 1.2  2002/09/18 20:48:21  lipp
* Cleanly separated workflow engine and service.
*
* Revision 1.1  2002/09/18 14:29:44  lipp
* Partial workflow service implementation added.
*
*/
package de.danet.an.workflow.ejbs.client;

import java.io.IOException;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.rmi.RemoteException;
import java.security.Principal;

import javax.jms.ConnectionConsumer;
import javax.jms.ConnectionFactory;
import javax.jms.ConnectionMetaData;
import javax.jms.Destination;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import javax.jms.ServerSessionPool;
import javax.jms.Session;
import javax.jms.Topic;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicSession;
import javax.jms.TopicSubscriber;
import javax.naming.Context;
import javax.naming.NamingException;

import de.danet.an.util.EJBUtil;
import de.danet.an.util.logging.RequestLog;

import de.danet.an.workflow.omgcore.CannotCompleteException;
import de.danet.an.workflow.omgcore.InvalidDataException;
import de.danet.an.workflow.omgcore.InvalidPerformerException;
import de.danet.an.workflow.omgcore.ProcessData;
import de.danet.an.workflow.omgcore.WfActivity;
import de.danet.an.workflow.omgcore.WfAuditEvent;
import de.danet.an.workflow.omgcore.WfAuditHandler;
import de.danet.an.workflow.omgcore.WfObject;
import de.danet.an.workflow.omgcore.WfProcess;
import de.danet.an.workflow.omgcore.WfRequester;
import de.danet.an.workflow.omgcore.WfResource;

import de.danet.an.workflow.api.Batch;
import de.danet.an.workflow.api.Channel;
import de.danet.an.workflow.api.Configuration;
import de.danet.an.workflow.api.EventSubscriber;
import de.danet.an.workflow.api.InvalidKeyException;
import de.danet.an.workflow.api.Process;
import de.danet.an.workflow.api.ProcessDefinitionDirectory;
import de.danet.an.workflow.api.ProcessDirectory;
import de.danet.an.workflow.api.WorkflowService;

import de.danet.an.workflow.apix.ExtProcessDirectory;
import de.danet.an.workflow.ejbs.WorkflowEngine;

/**
* This class provides the implementation of
* {@link WorkflowService <code>WorkflowService</code>}.<P>
*
* If loglevel is <code>DEBUG</code>, every event subscriber created
* with {@link #createEventSubscriber
* <code>createEventReceiver</code>} logs the received events.
*
* @author <a href="mailto:lipp@danet.de"></a>
* @version $Revision: 2930 $
*/

public class StandardWorkflowService
    implements WorkflowService, WfAuditHandler {

    private static final org.apache.commons.logging.Log logger
  = org.apache.commons.logging.LogFactory.getLog
  (StandardWorkflowService.class);

    private Map serviceProperties = null;

    private Context initialContext = null;

    private Boolean jmsConnectionReusable = null;
    private TopicConnectionFactory topConFacCache = null;
    private TopicConnection topConUnwrappedCache = null;
    private TopicConnection topConCache = null;
    private Thread connectionCleanupThread = null;
    private Topic eventService = null;
    private Topic channelMessageOutTopic = null;

    private EventSubscriber reqEvtRec = null;
    private Map reqsByProcKey = null;
    private Map procKeysByReq = null;
    private Collection ignoredProcs = null;

    private ReferenceQueue reqRefQueue = null;
    private Thread reqRefCleaner = null;

    private WorkflowEngine engine = null;

    /**
     * Creates an instance of <code>StandardWorkflowService</code>
     * with all attributes initialized to default values.
     *
     * @param props the service properties
     * @param ic the initial context to be used for lookup of server
     * resources
     * @param e the workflow engine
     */
    public StandardWorkflowService (Map props, Context ic, WorkflowEngine e) {
        serviceProperties = props;
        initialContext = ic;
        engine = e;
    }

    /**
     * Return the underlying workflow engine. Only for internal use.
     * @return the engine
     */
    public WorkflowEngine engine() {
        return engine;
    }
   
    private void initJmsSetup ()
  throws RemoteException, JMSException {
        if (topConFacCache != null) {
            return;
        }
  Object[] esd = engine.eventServiceData ();
  try {
      // This is a hack, but if anybody knowns a better way to
      // adapt to the application server used, please tell
      // me. This will eventually go away when JBoss gets a
      // client container, as we have application server
      // specific binding on the client side then.
      String conFacName = (String)esd[0];
      String topicConFacName = (String)esd[2];
           
            ConnectionFactory jbossInternalConFac = null;
            try {
                jbossInternalConFac = (ConnectionFactory)
                    initialContext.lookup ("java:/JmsXA");
            } catch (NamingException e) {
                // deliberately ignored
            }
            if (jbossInternalConFac == null) {
                try {
                    jbossInternalConFac = (ConnectionFactory)
                        initialContext.lookup ("java:XAConnectionFactory");
                } catch (NamingException e) {
                    // deliberately ignored
                }
            }
      // Comparison to "null" is workaround for JOnAS bug #300555
      if (jbossInternalConFac != null) {
    topConFacCache = (TopicConnectionFactory)jbossInternalConFac;
      } else if (conFacName != null && !conFacName.equals ("null")) {
    // Use this if your AS provides a factory that
    // implements both Queue- and TopicConnectionFactory
    topConFacCache = (TopicConnectionFactory)
        initialContext.lookup (conFacName);
      } else {
    if (topicConFacName == null
        || topicConFacName.equals ("null")) {
        if (engine.getClass().getName().startsWith
      ("de.danet.an.workflow.ejbs.JOnASWorkflowEngine")) {
      topicConFacName = "JTCF";
        } else {
      // popular default
      topicConFacName = "ConnectionFactory";
        }
    }
    topConFacCache = (TopicConnectionFactory)
        initialContext.lookup(topicConFacName);
      }
      eventService = (Topic)initialContext.lookup ((String)esd[3]);
      channelMessageOutTopic = (Topic)
    initialContext.lookup ((String)esd[4]);
  } catch (NamingException e) {
      logger.error (e.getMessage (), e);
      throw new IllegalStateException (e.getMessage ());
  }
    }

    /**
     * Return a started topic connection.
     * @return the connection
     * @throws RemoteException if a system-level error occurs
     * @throws JMSException if the connection cannot be created
     */
    TopicConnection topicConnection()
  throws RemoteException, JMSException {
  synchronized (this) {
            if (topConCache != null) {
                return topConCache;
            }
            if (jmsConnectionReusable == null) {
                initJmsSetup();
                // Crude, but currently the only known way to find out
                // whether we're running in server or client container.
                // And we need to know because of J2EE 1.4 spec, J2EE.6.6.
                TopicConnection topCon
                    = topConFacCache.createTopicConnection();
                topCon.start ();
                jmsConnectionReusable = Boolean.FALSE;
                TopicSession ts1 = null;
                TopicSession ts2 = null;
                try {
                    ts1 = topCon.createTopicSession
                        (false, Session.AUTO_ACKNOWLEDGE);
                    ts2 = topCon.createTopicSession
                        (false, Session.AUTO_ACKNOWLEDGE);
                    jmsConnectionReusable = Boolean.TRUE;
                } catch (JMSException e) {
                    // the created topic connection may still be handed out
                    return topCon;
                } finally {
                    if (ts1 != null) {
                        ts1.close();
                    }
                    if (ts2 != null) {
                        ts2.close();
                    }
                }
                topConUnwrappedCache = topCon;
                topConCache = new TopicConnectionWrapper (topCon);
                connectionCleanupThread = new Thread () {
                    public void run () {
                        if (topConUnwrappedCache != null) {
                            try {
                                topConUnwrappedCache.close ();
                            } catch (JMSException e) {
                                logger.warn ("Cannot close - ignored: "
                                             + e.getMessage(), e);
                            }
                            topConCache = null;
                            topConUnwrappedCache = null;
                        }
                    }
                };
                Runtime.getRuntime().addShutdownHook (connectionCleanupThread);
                return topConCache;
            }
  }
  TopicConnection topCon = ((TopicConnectionFactory)topConFacCache)
            .createTopicConnection();
        topCon.start ();
        return topCon;
    }

    private class EventSubscriberImpl implements EventSubscriber {

        private TopicConnection connection;
  private TopicSession session;
  private TopicSubscriber subs;

  public EventSubscriberImpl (String processKey, String eventTypes)
      throws IOException {
      try {
                initJmsSetup();
                connection = topicConnection();
    session = connection.createTopicSession
        (false, Session.AUTO_ACKNOWLEDGE);
    if (processKey == null && eventTypes == null) {
        subs = session.createSubscriber (eventService);
        return;
    }
    StringBuffer filter = new StringBuffer ();
    if (processKey != null) {
        filter.append ("processKey = '" + processKey + "'");
    }
    if (eventTypes != null) {
        if (filter.length() > 0) {
      filter.append (" AND ");
        }
        filter.append ("(");
        StringTokenizer st
      = new StringTokenizer (eventTypes, " \t\n\r\f,;");
        boolean first = true;
        while (st.hasMoreTokens ()) {
      if (first) {
          first = false;
      } else {
          filter.append (" OR ");
      }
      filter.append ("(eventType = '");
      filter.append (st.nextToken());
      filter.append ("')");
        }
        if (first) {
      throw new IllegalArgumentException
          ("\"" + eventTypes + "\" is not a"
           + " valid list of event types.");
        }
        filter.append (")");
    }
    subs = session.createSubscriber
        (eventService, filter.toString (), true);
    if (logger.isDebugEnabled ()) {
        logger.debug ("Created " + this + " with filter \""
          + filter.toString () + "\"");
    }
      } catch (JMSException e) {
    throw (IOException)
        (new IOException (e.getMessage())).initCause (e);
      }
  }

  public void close () {
      try {
    subs.close ();
    session.close ();
                connection.close ();
      } catch (JMSException e) {
    logger.error ("Closing topic: " + e.getMessage (), e);
      }
            subs = null;
            session = null;
            connection = null;
  }

  public WfAuditEvent receive () throws IOException {
      try {
    Object e = ((ObjectMessage)subs.receive()).getObject();
    if (logger.isDebugEnabled()) {
        logger.debug ("EventSubscriber " + this + " received " + e);
    }
    return (WfAuditEvent)e;
      } catch (JMSException e) {
    throw (IOException)
        (new IOException (e.getMessage())).initCause (e);
      }
  }
  public WfAuditEvent receive (long timeout) throws IOException {
      try {
    Object e = subs.receive(timeout);
    if (e == null) {
        return null;
    }
    e = ((ObjectMessage)e).getObject();
    if (logger.isDebugEnabled()) {
        logger.debug ("EventSubscriber " + this + " received " + e);
    }
    return (WfAuditEvent)e;
      } catch (JMSException e) {
    throw (IOException)
        (new IOException (e.getMessage())).initCause (e);
      }
  }
  public WfAuditEvent receiveNoWait () throws IOException {
      try {
    Object e = ((ObjectMessage)subs.receiveNoWait()).getObject();
    if (e == null) {
        return null;
    }
    if (logger.isDebugEnabled()) {
        logger.debug ("EventSubscriber " + this + " received " + e);
    }
    return (WfAuditEvent)e;
      } catch (JMSException e) {
    throw (IOException)
        (new IOException (e.getMessage())).initCause (e);
      }
  }

  public void setEventHandler (WfAuditHandler hndlr) throws IOException {
      final WfAuditHandler handler = hndlr;
      try {
    subs.setMessageListener (new MessageListener () {
      public void onMessage (Message msg) {
          Object e = null;
          try {
        e = ((ObjectMessage)msg).getObject();
        if (logger.isDebugEnabled()) {
            logger.debug
          ("EventSubscriber " + this
           + " received " + e
           + " with processKey="
           + msg.getStringProperty("processKey")
           + " and eventType="
           + msg.getStringProperty("eventType"));
        }
        handler.receiveEvent((WfAuditEvent)e);
          } catch (JMSException ex) {
        logger.error (ex.getMessage (), ex);
          } catch (InvalidPerformerException ex) {
        // deliberatly ignored.
          } catch (RemoteException ex) {
        // deliberatly ignored.
          } catch (Exception ex) {
        logger.error (this + "cannot handle " + e
                + ": " + ex.getMessage (), ex);
          }
      }
        });
      } catch (JMSException e) {
    throw (IOException)
        (new IOException (e.getMessage())).initCause (e);
      }
  }
    }

    /* Comment copied from interface. */
    public Map serviceProperties () throws RemoteException {
  return serviceProperties;
    }

    /* Comment copied from interface. */
    public Configuration configuration() throws RemoteException {
  return engine.configuration();
    }

    /* Comment copied from interface. */
    public ProcessDefinitionDirectory processDefinitionDirectory()
  throws RemoteException {
  return engine.processDefinitionDirectory();
    }

    /* Comment copied from interface. */
    public ProcessDirectory processDirectory() throws RemoteException {
  return engine.processDirectory();
    }

    /* Comment copied from interface. */
    public Collection knownResources ()  throws RemoteException {
  return engine.knownResources();
    }

    /* Comment copied from interface. */
    public WfResource resourceByKey (String key)
  throws InvalidKeyException, RemoteException {
  return engine.resourceByKey(key);
    }

    /* Comment copied from interface. */
    public Collection authorizers (WfResource resource)
  throws RemoteException {
  return engine.authorizers(resource);
    }

    /* Comment copied from interface. */
    public WfResource asResource (Principal principal)
  throws RemoteException, InvalidKeyException {
  return engine.asResource(principal);
    }

    /* Comment copied from interface. */
    public Collection requestedBy (WfRequester req)
  throws RemoteException {
  return ((ExtProcessDirectory)
    engine.processDirectory()).requestedBy (req);
    }

    /* Comment copied from interface. */
    public void doFinish (WfActivity act, ProcessData result)
  throws InvalidDataException, CannotCompleteException, RemoteException {
  engine.doFinish (act, result);
    }

    /* Comment copied from interface. */
    public Object executeBatch (Batch batch)
  throws RemoteException, InvocationTargetException {
  return engine.executeBatch (batch);
    }

    /* Comment copied from interface. */
    public WfObject eventReceiver (WfAuditHandler handler)
  throws RemoteException {
  try {
      EventSubscriber es = new EventSubscriberImpl (null, null);
      es.setEventHandler (handler);
      return es;
  } catch (IOException e) {
      // This mapping is wrong but backward compatible, and the
      // method now deprecated anyway.
      throw (RemoteException)
    (new RemoteException (e.getMessage())).initCause (e);
  }
    }
   
    /* Comment copied from interface. */
    public EventSubscriber createEventSubscriber () throws IOException {
  return new EventSubscriberImpl (null, null);
    }

    /* Comment copied from interface. */
    public EventSubscriber createEventSubscriber
  (String processKey, String eventTypes) throws IOException {
  return new EventSubscriberImpl (processKey, eventTypes);
    }
   
    /* Comment copied from interface. */
    public void registerRequester (WfRequester requester)
  throws RemoteException {
  synchronized (this) {
      if (reqEvtRec == null) {
    try {
        reqEvtRec = createEventSubscriber ();
        reqEvtRec.setEventHandler (this);
    } catch (IOException e) {
        throw (IllegalStateException)
      (new IllegalStateException
       (e.getMessage())).initCause (e);
    }
    reqsByProcKey = new HashMap ();
    procKeysByReq = new HashMap ();
    ignoredProcs = new ArrayList ();
    reqRefQueue = new ReferenceQueue ();
    reqRefCleaner = new Thread () {
      public void run () {
          while (true) {
        try {
            Reference ref = reqRefQueue.remove ();
            synchronized
          (StandardWorkflowService.this) {
          Set procKeys
              = (Set)procKeysByReq.remove (ref);
          for (Iterator i = procKeys.iterator ();
               i.hasNext();) {
              reqsByProcKey.remove
            ((String)i.next());
          }
            }
        } catch (InterruptedException e) {
            // deliberatly ignored
        }
          }
      }
        };
    reqRefCleaner.setDaemon (true);
    reqRefCleaner.start ();
      }
      procKeysByReq.put (new WeakReference (requester, reqRefQueue),
             new HashSet());
      // we could demand a requester to be registered before first
      // use and thus avoid rebuilding ignoredProcs after every
      // registration. But then we would need elaborate code to
      // clean out old process keys from the ignoredProcs set...
      ignoredProcs.clear ();
  }
    }

    /**
     * Receive an event and distribute it to the appropriate handler.
     *
     * @param evt the event.
     * @throws InvalidPerformerException thrown by the derived
     * {@link de.danet.an.workflow.omgcore.WfRequester
     * <code>WfRequester</code>} if it receives an event from a
     * process that is not among its performers.
     * @throws RemoteException if a system-level error occurs.
     */
    public void receiveEvent (WfAuditEvent evt)
  throws InvalidPerformerException, RemoteException {
  try {
      String procKey = evt.processKey();
      WfRequester requester = null;
      synchronized (this) {
    WeakReference requesterRef
        = (WeakReference)reqsByProcKey.get(procKey);
    if (requesterRef != null) {
        requester = (WfRequester)requesterRef.get();
    }
    if (requester == null) {
        // if we know that none of ours handles it, discard
        if (ignoredProcs.contains (procKey)) {
      return;
        }
        // try to find handler
        found:
        for (Iterator i = procKeysByReq.keySet().iterator();
       i.hasNext();) {
      WeakReference reqRef = (WeakReference)i.next();
      WfRequester req = (WfRequester)reqRef.get();
      if (req == null) {
          continue;
      }
      Set assocKeys = (Set)procKeysByReq.get (reqRef);
      Collection perfs = ((WfRequester)req).performers();
      for (Iterator p = perfs.iterator(); p.hasNext();) {
          WfProcess perf = (WfProcess)p.next();
          String pk = perf.key();
          reqsByProcKey.put (pk, reqRef);
          assocKeys.add (pk);
          if (pk.equals (procKey)) {
        requester = req;
        break found;
          }
      }
        }
        if (requester == null) {
      ignoredProcs.add (procKey);
        }
    }
      }
      // if we know, who handles this, forward (outside sync!)
      if (requester != null) {
    requester.receiveEvent(evt);
      }
  } catch (InvalidPerformerException e) {
      // deliberately ignored.
  } catch (RemoteException e) {
      // deliberately ignored.
  }
    }

    /**
     * Return the channel messages out topic.
     * @return the topic
     */
    Topic channelMessageOutTopic () {
  return channelMessageOutTopic;
    }

    /* Comment copied from interface. */
    public Channel getChannel (WfProcess process, String channelName)
  throws RemoteException {
  return new ChannelImpl (this, (Process)process, channelName, false);
    }

    /* Comment copied from interface. */
    public Channel getChannel
        (WfProcess process, String channelName, boolean sendOnly)
        throws RemoteException {
        return new ChannelImpl (this, (Process)process, channelName, sendOnly);
    }

    /**
     * Free any allocated resources.
     */
    public void release () {
        if (connectionCleanupThread != null) {
            Runtime.getRuntime()
                .removeShutdownHook(connectionCleanupThread);
            connectionCleanupThread.run();
            connectionCleanupThread = null;
        }
        engine = null;
    }

    /* Comment copied from interface. */
    public void release (WfObject obj) {
  if (obj instanceof EventSubscriberImpl) {
      ((EventSubscriberImpl)obj).close();
      return;
  }
  if (obj instanceof ChannelImpl) {
      ((ChannelImpl)obj).release();
      return;
  }
        if (obj instanceof StandardWorkflowService) {
            ((StandardWorkflowService)obj).release();
            return;
        }
  EJBUtil.removeSession (obj);
    }

    /* (non-Javadoc)
     * @see de.danet.an.workflow.api.WorkflowService#caller()
     */
    public Principal caller() throws RemoteException {
        return engine.caller();
    }

    /**
     * This class provides a wrapper around a topic connection that
     * prevents it from being stopped or closed (redefined to noop).
     *
     * @author Michael Lipp
     *
     */
    public static class TopicConnectionWrapper implements TopicConnection {
        private TopicConnection delegee;

        /**
         * Create a new instance with all attributes initialized
         * to defaults or the given values.
         *
         * @param delegee
         */
        public TopicConnectionWrapper(TopicConnection delegee) {
            this.delegee = delegee;
        }

        /**
         * @throws JMSException
         * @see javax.jms.Connection#close()
         */
        public void close() throws JMSException {
        }

        /**
         * @param arg0
         * @param arg1
         * @param arg2
         * @param arg3
         * @return
         * @throws JMSException
         * @see javax.jms.Connection#createConnectionConsumer(javax.jms.Destination, java.lang.String, javax.jms.ServerSessionPool, int)
         */
        public ConnectionConsumer createConnectionConsumer(Destination arg0, String arg1, ServerSessionPool arg2, int arg3) throws JMSException {
            return delegee.createConnectionConsumer(arg0, arg1, arg2, arg3);
        }

        /**
         * @param arg0
         * @param arg1
         * @param arg2
         * @param arg3
         * @return
         * @throws JMSException
         * @see javax.jms.TopicConnection#createConnectionConsumer(javax.jms.Topic, java.lang.String, javax.jms.ServerSessionPool, int)
         */
        public ConnectionConsumer createConnectionConsumer(Topic arg0, String arg1, ServerSessionPool arg2, int arg3) throws JMSException {
            return delegee.createConnectionConsumer(arg0, arg1, arg2, arg3);
        }

        /**
         * @param arg0
         * @param arg1
         * @param arg2
         * @param arg3
         * @param arg4
         * @return
         * @throws JMSException
         * @see javax.jms.TopicConnection#createDurableConnectionConsumer(javax.jms.Topic, java.lang.String, java.lang.String, javax.jms.ServerSessionPool, int)
         */
        public ConnectionConsumer createDurableConnectionConsumer(Topic arg0, String arg1, String arg2, ServerSessionPool arg3, int arg4) throws JMSException {
            return delegee.createDurableConnectionConsumer(arg0, arg1, arg2, arg3, arg4);
        }

        /**
         * @param arg0
         * @param arg1
         * @return
         * @throws JMSException
         * @see javax.jms.Connection#createSession(boolean, int)
         */
        public Session createSession(boolean arg0, int arg1) throws JMSException {
            return delegee.createSession(arg0, arg1);
        }

        /**
         * @param arg0
         * @param arg1
         * @return
         * @throws JMSException
         * @see javax.jms.TopicConnection#createTopicSession(boolean, int)
         */
        public TopicSession createTopicSession(boolean arg0, int arg1) throws JMSException {
            return delegee.createTopicSession(arg0, arg1);
        }

        /**
         * @return
         * @throws JMSException
         * @see javax.jms.Connection#getClientID()
         */
        public String getClientID() throws JMSException {
            return delegee.getClientID();
        }

        /**
         * @return
         * @throws JMSException
         * @see javax.jms.Connection#getExceptionListener()
         */
        public ExceptionListener getExceptionListener() throws JMSException {
            return delegee.getExceptionListener();
        }

        /**
         * @return
         * @throws JMSException
         * @see javax.jms.Connection#getMetaData()
         */
        public ConnectionMetaData getMetaData() throws JMSException {
            return delegee.getMetaData();
        }

        /**
         * @param arg0
         * @throws JMSException
         * @see javax.jms.Connection#setClientID(java.lang.String)
         */
        public void setClientID(String arg0) throws JMSException {
            delegee.setClientID(arg0);
        }

        /**
         * @param arg0
         * @throws JMSException
         * @see javax.jms.Connection#setExceptionListener(javax.jms.ExceptionListener)
         */
        public void setExceptionListener(ExceptionListener arg0) throws JMSException {
            delegee.setExceptionListener(arg0);
        }

        /**
         * @throws JMSException
         * @see javax.jms.Connection#start()
         */
        public void start() throws JMSException {
            delegee.start();
        }

        /**
         * @throws JMSException
         * @see javax.jms.Connection#stop()
         */
        public void stop() throws JMSException {
        }
    }
}
TOP

Related Classes of de.danet.an.workflow.ejbs.client.StandardWorkflowService$EventSubscriberImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.