javanetbridgeinteropclass.cs

来自「SRI international 发布的OAA框架软件」· CS 代码 · 共 301 行

CS
301
字号
using System;
using System.Collections;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using jnb.java.lang;

namespace jnb.com.sri.sedc.javanetbridge
{
	public abstract class JavaNetBridgeInteropClass
	{
		protected Hashtable callbackMap = new Hashtable();
		protected Hashtable objectDatabase = new Hashtable();
		protected CSharpDataMarshalOutputStream dout;
		protected CSharpDataMarshalInputStream din;
		protected CSharpDataMarshalOutputStream callbackout;
		protected CSharpDataMarshalInputStream callbackin;
		protected const byte METHOD_INVOKE_GOOD_RET = (byte)0;
		protected const byte METHOD_INVOKE_VOID_RET = (byte)1;
		protected const byte METHOD_INVOKE_EXCEPTION = (byte)2;
		protected const byte INVOKE_INDICATOR = (byte)3;
		protected const byte CALLBACK_INDICATOR = (byte)4;
        protected const byte INVOKE_REENTRANT_INDICATOR = (byte)5;
        protected JavaNetBridgeBean bean;
		Mutex objectDatabaseLock = new Mutex();
		Mutex methodInvokeLock = new Mutex();
		private static IPAddress connectAddress = IPAddress.Loopback;
		private static int connectPort = 4016;
		protected static bool reentrant = true;
		private static bool started = false;
		private Hashtable reentrantThreads = new Hashtable();
		private Hashtable reentrantThreadIds = new Hashtable();
		private int reentrantThreadId = 0;

		public Hashtable getCallbackMap()
		{
			return callbackMap;
		}

		public void handleSocketException(System.Net.Sockets.SocketException ex)
		{
			throw ex;
		}

		public abstract String getIDString();
		public abstract String getDateString();

		public void initUsingSocket()
		{
			started = true;
			Socket connection = new Socket(AddressFamily.Unspecified, SocketType.Stream,
				ProtocolType.Tcp);
			connection.Connect(new IPEndPoint(connectAddress, connectPort));
			Socket callbackConnection = new Socket(AddressFamily.Unspecified, SocketType.Stream,
				ProtocolType.Tcp);
			callbackConnection.Connect(new IPEndPoint(connectAddress, connectPort));
			dout = new CSharpDataMarshalOutputStreamImpl(connection);
			din = new CSharpDataMarshalInputStreamImpl(connection);
			callbackout = new CSharpDataMarshalOutputStreamImpl(callbackConnection);
			callbackin = new CSharpDataMarshalInputStreamImpl(callbackConnection);
			dout.write(getIDString());
			dout.write(getDateString());
			dout.write("New");
			int id = din.readInt();
			callbackout.write(getIDString());
			callbackout.write(getDateString());
			callbackout.write("AttachCallback");
			callbackout.write(id);

			// Start a thread to receive callback notifications
			Thread callbackThread = new Thread(new ThreadStart(readCallbacks));
			callbackThread.Start();

			if (reentrant) {
				// Start a thread to receive the results of method calls
				Thread readReturnThread = new Thread(new ThreadStart(readMethodReturns));
				readReturnThread.Start();
			}
		}

		public static IPAddress getConnectAddress() 
		{
			return connectAddress;
		}

		public static void setConnectAddress(IPAddress address) 
		{
			if (started) {
				throw new Exception("setConnectAddress: The connection to the dotnetproxy has already been initiated. Cannot set the proxy host.");
			}
			connectAddress = address;
		}

		public static bool isReentrant() {
			return reentrant;
		}

		public static void setReentrant(bool isreentrant) {
			if (started) {
				throw new Exception("setConnectPort: The connection to the dotnetproxy has already been initiated. Cannot set reeentrant to " + reentrant);
			}
			reentrant = isreentrant;
		}

		public static int getConnectPort() 
		{
			return connectPort;
		}

		public static void setConnectPort(int port) 
		{
			if (started) {
				throw new Exception("setConnectPort: The connection to the dotnetproxy has already been initiated. Cannot set the proxy port.");
			}
			connectPort = port;
		}

		public abstract Object newCSharpObjectForJavaObject(JavaObjectId id, bool addRef, String defaultClassName);

		public Object getCSharpObjectForJavaObject(JavaObjectId id, bool addRefOnNew, String defaultClassName) 
		{
			objectDatabaseLock.WaitOne();
			try 
			{
				Object ret = objectDatabase[id.getId()];
				if (ret != null) 
				{
					ret = ((WeakReference)ret).Target;
				}
				if (ret != null) 
				{
					return ret;
				} 
				else 
				{
					if (objectDatabase.Contains(id.getId())) 
					{
						objectDatabase.Remove(id.getId());
					}
					ret = newCSharpObjectForJavaObject(id, addRefOnNew, defaultClassName);
					objectDatabase.Add(id.getId(), new WeakReference(ret));
					return ret;
				}
			}
			finally 
			{
				objectDatabaseLock.ReleaseMutex();
			}
		}

		public void notifyCallbackFromPool(Object callbackId) {
			notifyCallback((int)callbackId);
		}

		public void notifyCallback(int callbackId)
		{
			notifyCallback(new CallbackParams_StubImpl(new JavaObjectId(callbackId,
				CallbackParams_StubImpl.JAVA_CLASS_NAME), false));
		}

		void readCallbacks()
		{
			while (true)
			{
				byte indicator = callbackin.readByte();
				if (indicator == CALLBACK_INDICATOR)
				{
					int callBackObjId = callbackin.readInt();
					if (!reentrant) {
						notifyCallback(callBackObjId);
					} else {
						ThreadPool.QueueUserWorkItem(new WaitCallback(notifyCallbackFromPool), callBackObjId);
					}
				}
			}
		}

		public void methodCallLock()
		{
			methodInvokeLock.WaitOne();
		}

		public void methodCallRelease()
		{
			methodInvokeLock.ReleaseMutex();
		}

		private Thread reeentrantMethodReturnReader;
		private volatile int currentThreadId;
		private Object reentrantLock = new Object();
		private bool waitingForRead = false;

		void readMethodReturns() {
			reeentrantMethodReturnReader = Thread.CurrentThread;
			while (true)
			{
				currentThreadId = din.readInt();
				// There should be a thread waiting for the results. If there is not, then
				// this may indicate a fatal error.
				if (reentrantThreadIds.Contains(currentThreadId)) {
					Object threadObj = reentrantThreadIds[currentThreadId];
					lock (threadObj) {
						Monitor.Pulse(threadObj);
						waitingForRead = true;
					}
					// Wait for the thread to finish reading the results...
					lock (reentrantLock) {
						if (waitingForRead) {
							Monitor.Wait(reentrantLock);
							waitingForRead = false;
						}
					}
				} else {
					Console.Error.WriteLine("Error: received unknown thread id: " + currentThreadId);
				}
			}
		}

		protected void notifyMethodReturnRead() {
			lock (reentrantLock) {
				waitingForRead = false;
				Monitor.Pulse(reentrantLock);
			}
		}

		protected int registerReentrantThread() {
			Thread currentThread = Thread.CurrentThread;
			// If there is no thread id associated with this thread, assign a new id
			if (!reentrantThreads.Contains(currentThread)) {
				reentrantThreadId++;
				reentrantThreads[currentThread] = reentrantThreadId;
				reentrantThreadIds[reentrantThreadId] = currentThread;
			}
			return (int)reentrantThreads[currentThread];
		}

		protected void waitForMethodResponse() {
			Thread currentThread = Thread.CurrentThread;
			lock (currentThread) {
				bool needsSuspend = true;
				lock (reentrantLock) {
					if (waitingForRead) {
						// Return thread is waiting on reentrantLock. If it is waiting for this thread,
						// then there is no need to suspend.
						int currentId = currentThreadId;
						int threadId = (int)reentrantThreads[Thread.CurrentThread];
						if (threadId == currentId) {
							needsSuspend = false;
						}
					}
				}
				if (needsSuspend) {
					Monitor.Wait(currentThread);
				}
			}
		}

		public void notifyCallback(CallbackParams cparams)
		{
			try
			{
				int sourceId = cparams.getSource();
				if (callbackMap.Contains(sourceId))
				{
					((CSharpCallbackImpl)callbackMap[sourceId]).doCallback(cparams);
				}
			}
			finally
			{
				bean.notifyCallbackDone(cparams);
			}
		}

		public JavaObjectId newCallback(String javaCallbackClass)
		{
			return new JavaObjectId(bean.newCallback(javaCallbackClass), javaCallbackClass);
		}

		public void readAndThrowSocketException()
		{
			try
			{
				String className = din.readString();
				String message = din.readString();
				throw new System.Exception("Java Invocation Exception: " +
					className + ": " + message + ", Calling stack trace is: " +
					new System.Diagnostics.StackTrace());
			}
			catch (System.Net.Sockets.SocketException ex)
			{
				handleSocketException(ex);
			}
		}

		public void registerCallback(CSharpCallbackImpl impl, JavaObjectId id)
		{
			callbackMap.Add(id.getId(), impl);
		}
	}
}

⌨️ 快捷键说明

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