cmiseventqueue.java

来自「CmisJavaApi」· Java 代码 · 共 301 行

JAVA
301
字号
/* * The contents of this file are subject to the Dyade Public License,  * as defined by the file DYADE_PUBLIC_LICENSE.TXT * * You may not use this file except in compliance with the License. You may * obtain a copy of the License on the Dyade web site (www.dyade.fr). * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for * the specific terms governing rights and limitations under the License. * * The Original Code is CmisJava API, including the java package  * fr.dyade.cmis, released September 5, 2000. * * The Initial Developer of the Original Code is Dyade. The Original Code and * portions created by Dyade are Copyright Bull and Copyright INRIA.  * All Rights Reserved. *//*      Copyright 1996-2000 by Institut National de Recherche en Informatique  *                             et en Automatique (INRIA) *          All rights reserved.  See COPYRIGHT in top-level directory. * *      Authors: Laurent Andrey, Eric Dillon, Olivier Festor *///  $Id: CMISEventQueue.java,v 1.2 2000/09/05 14:30:30 festor Exp $//  $Source: /local/resedas/CVS-Repository/CmisJavaApi/src/fr/dyade/cmis/impl/CMISEventQueue.java,v $//// TODO//// - priority feature ? (i.e several queues and several threads with various priority)// - make a CLEAN sepation between interface and implementation ?package fr.dyade.cmis.impl;import fr.dyade.cmis.api.CMISStack;import fr.dyade.cmis.api.CMISException;import fr.dyade.cmis.api.operation.event.CMISEvent;import fr.dyade.cmis.api.operation.event.CMISEventSource;import fr.dyade.cmis.api.operation.event.InternalErrorEvent;import fr.dyade.cmis.util.TraceManager;/** Event Queue and event dispatcher.  * Data structure to keep events generated by transport level (indications, confirmations) or   * various asynchronous errors. This class also features a   * thread to dispatch event to source and then call the  * proper behavior (listener).   *  * This structure is used by the   * {@link CMISStackImpl "generic implementation"}. The same event queue can be shared by   * several CMISStack instances: see {@link CMISStackImpl#CMISStackImpl(CMISEventQueue)   * dedicated constructor} or concrete implementations ones:   * {@link fr.dyade.cmis.rmi.AgentImpl#AgentImpl(String,CMISEventQueue)} or  * {@link fr.dyade.cmis.om.OMBinding#OMBinding(CMISEventQueue)}.  *   * Code sample:  * <code>         import fr.dyade.cmis.impl.CMISEventQueue;	 import fr.dyade.cmis.rmi.AgentImpl;	 import fr.dyade.cmis.om.OMBinding;         ....  	 CMISEventQueue commonQueue=new CMISEventQueue();	 ....	 AgentImpl agentrmi=new AgentImpl(registrationName, commonQueue);	 OMBinding omfmk= new OMBinding(commonQueue);	 ...  </code>  *  * NOTE: this structure is very alike awt event queue.  *  * @version cvs $Id: CMISEventQueue.java,v 1.2 2000/09/05 14:30:30 festor Exp $  */public class CMISEventQueue {      class CMISEventQueueItem {	    CMISEvent event;	    CMISEventQueueItem next;	    	    CMISEventQueueItem(CMISEvent evt) {	       event = evt;	    }      }      final class CMISEventDispatchThread extends Thread {	    private CMISEventQueue theQueue;	    private boolean doDispatch = true;	    CMISEventDispatchThread(String name, CMISEventQueue queue) {	       super(name);	       theQueue = queue;	    }	    /** Stop the thread.	      * Remark: <tt>Thread.stop()</tt> is deprecated in JDK 1.2.	      * This method is to be use only be <tt>CMISEventQueue.stopDispatching()</tt>.	      */	    final void stopDispatching() {	       TraceManager.debugln("stop CMIS event dispatching");	       doDispatch = false;	       interrupt(); // This thread is usually blocked in getNextEvent.	       //LA: todo: a nice way would be to define a "LastEvent", posted 	       //by the listening "poster" thread(S) & keep track of the registered "posters" for this queue.	    }	    final public void run() {	       // exception reporting via InternalErrorEvent at this place	       // is not far away from yet another uggly hack (YAUH !). But	       // life is...	       while (doDispatch) {		  CMISEvent event=null;		  try {		     event = theQueue.getNextEvent();		     theQueue.dispatchEvent(event);		  } catch (ThreadDeath death) {		     return;		  } catch (InterruptedException interruption) {		     // InterruptedException can occur. See fr.dyade.cmis.om.OMListeningThread.stopDispatching()		     // nothing we continue, may be this interruption is due to an an update		     // to the "doDispatch" state variable and so may be this run() method will		     // complete in a "clean" way.		  } catch (Throwable other) {		     // catch any other exception what occurred during event dispatching and processing.		     // add error handling, but filtering any pb....		     try {			CMISStackImpl st=(CMISStackImpl)event._getStack();			if (event instanceof InternalErrorEvent) {			   // DO NOT REPOST TROUBLE ABOUT TROUBLE !			   // use  last chance handler			   st.callSynchronousErrorHandler(other);			} else {			   // post an InternalErrorEvent.			   postUrgentEvent(new InternalErrorEvent(st, other));			}				     } catch (Throwable other2) {			// not InternalErrorEvent post, just last chance handler.			try {			   ((CMISStackImpl)event._getStack()).callSynchronousErrorHandler(other2);			} catch (Throwable other3) {			   if (TraceManager.isDebugOn()) {			      System.err.println("Bad bad bad Exception occurred during event dispatching:");			      other3.printStackTrace();			   }			}		     }		  }	       }	       TraceManager.debugln(getClass().getName()+": end run");	    }	    final boolean isDispatching(CMISEventQueue eq) {	       return theQueue.equals(eq);	    }	    final CMISEventQueue getEventQueue() { return theQueue; }      }      // From Thread.java      private static int threadInitNumber;      private static synchronized int nextThreadNum() {	 return threadInitNumber++;      }            /** Head to event queue.	* The actual queue of events, implemented as a linked-list. 	* We are keeping head  and  tail (true fifo access).	*/      CMISEventQueueItem fHead;      /** Tail of event queue.	*/      CMISEventQueueItem fTail;      public CMISEventQueue() {	 fHead = null;	 fTail = null;	 String name = "CMIS-EventQueue-" + nextThreadNum();	 fDispatchingThread= new CMISEventDispatchThread(name, this);	 fDispatchingThread.start();      }      /** Post a new event at the tail of the queue 	* @param theEvent the regular event to post.	*/      public final synchronized void postEvent(CMISEvent theEvent) {	 CMISEventQueueItem eqi = new CMISEventQueueItem(theEvent);	 if (fTail == null) { // empty queue            fHead = eqi;	    fTail= eqi;            notifyAll();	 } else { // tail insertion	    fTail.next = eqi;	    fTail=eqi;	 }      }      /** Urgent event post (head insertion).	* This method is intended to be used to post	* {@link fr.dyade.cmis.api.operation.event.InternalErrorEvent} instances.	* @param theEvent the urgent event to post.	*/      public final synchronized void postUrgentEvent( CMISEvent theEvent ) {	 CMISEventQueueItem eqi = new CMISEventQueueItem(theEvent);	 if (fTail == null) { // empty queue            fHead = eqi;	    fTail= eqi;            notifyAll();	 } else { // head insertion	    eqi.next = fHead;	    fTail=eqi;	 }      }      /**	* Remove an event from the queue's head and return it.  	* This method will	* block until an event has been posted by another thread.	* @return the next CMISEvent	* @exception InterruptedException 	*            if another thread has interrupted this thread.	*/      public final synchronized CMISEvent getNextEvent() throws InterruptedException {	 while (fHead == null) {            wait();	 }	 CMISEventQueueItem eqi = fHead;	 fHead = fHead.next;	 if (fHead==null) {	    fTail=null;	 }	 return eqi.event;      }      /**	* Return the first event without removing it.	* @return the first event.	*/      public final synchronized CMISEvent peekEvent() {	 return (fHead != null) ? fHead.event : null;      }      /**	* Dispatch an event to its source.	*	* @param theEvent an instance of CMISEvent, or a	* subclass of it.	*/      final protected void dispatchEvent(CMISEvent event) throws CMISException {	 ((CMISEventSource)(event.getSource())).dispatchEvent(event);      }      /**	* Remove any pending events for the specified source object.	* This method is normally called by the source's removeNotify method.	* @param source the object source from which the queue must be clean up for events	*/      synchronized void removeSourceEvents(Object source) {	 CMISEventQueueItem entry = fHead;	 CMISEventQueueItem prev = null;	 while (entry != null) {            if (entry.event.getSource().equals(source)) {	       if (prev == null) {		  fHead = entry.next;	       } else {		  prev.next = entry.next;	       }            } else { /* LA?: add this else case.			When removing entry prev should not change ! */	       prev = entry;	    }            entry = entry.next;	 }	 fTail=prev;      }      /** Remove all events related to a stack.	* This method remove all event (CMISServiceEvent or CMISServiceRequestEvent)	* related to a given stack. Typically this method can be call when a stack is terminated	* (association closed).	* @param pStack to filter event in the queue.	*/      public synchronized void removeStackEvents( CMISStack pStack ) {	 CMISEventQueueItem entry = fHead;	 CMISEventQueueItem prev = null;	  while (entry != null) {            if (entry.event._getStack()==pStack) {	       if (prev == null) {		  fHead = entry.next;	       } else {		  prev.next = entry.next;	       }            } else { /* LA?: add this else case.			When removing entry prev should not change ! */	       prev = entry;	    }            entry = entry.next;	  }	  fTail=prev;      }      public void stopDispatching() {	 if (fDispatchingThread!=null) {	    fDispatchingThread.stopDispatching();	 }      }      private CMISEventDispatchThread fDispatchingThread;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?