⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 channelifaceinvocation.java

📁 这是外国一个开源推理机
💻 JAVA
字号:
/* *  Copyright (C) 2004 OntoText Lab, Sirma AI OOD * *  Address: *  Europe            135 Tsarigradsko Shose, Sofia 1784, Bulgaria *                    (IT Center Office Express, 3rd floor) * *  North America     438 Isabey Str, Suite 103, Montreal, Canada H4T 1V3 * *  Phone: (+359 2) 9768 310 *  Fax: (+359 2) 9768 311 * * *  E-mail:                          info@ontotext.com *  Web:                             http://www.ontotext.com *  Sirma Group International Corp.  http://www.sirma.com *  Sirma AI Ltd.                    http://www.sirma.bg * *  This library is free software; you can redistribute it and/or *  modify it under the terms of the GNU Lesser General Public *  License as published by the Free Software Foundation; either *  version 2.1 of the License, or (at your option) any later version. * *  This library 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 *  Lesser General Public License for more details. * *  You should have received a copy of the GNU Lesser General Public *  License along with this library; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */package org.openrdf.util.rmirouting;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;import java.rmi.Remote;import java.rmi.RemoteException;/** * <p>The implementation of client side wraper used to handle and then pass the * method invocation requests to the remote side of the channel.</p> * we should notice that all 'void' methods that have only native or Serailizable arguments * could be batched and passed at once at some future moment. This can be enable if the wrapped instance * implements a <code>Bachable</code> Interface. * <p>The rationale behind this is the assumption that such methods cannot change, in any other way, * the state of the invoking context unless they has some very important and significant side effects implemented. * <pThe technique is used to speed up such invocations by reducing the network traffic involved * and they prove to be very useful while working with listeners. The delayed methods are collected * in a 'Batch job' queue and on the invocation of non-vod method or a method which have some * other than Serializable or native argument passed, are commited to the remote side. * The same can happen if the local handler is being garbage collected or its queue gets full. * * @author Damyan Ognyanoff * @version 1.0 */public class ChannelIfaceInvocation implements InvocationHandler {	protected final static int JOB_QUEUE_SIZE = 250;	/**	 * a ref to the wrapped remote instace	 */	transient ChannelIface remoteInstance;	transient boolean bCanBatch;	/**	 * A static method used to wrap an remote ref ot an instance. Only remote refs implementing <code>ChannelIface</code>	 * will be wrapped	 * @param o is the ref to be wrapped	 * @return an wraped instance	 * @throws Exception	 */	public static Object wrapIt(Object o)		throws Exception	{		Class[] ifaces = null;		// if it it not implementing a ChannelIface  interface, we should skip it		if (false == o instanceof ChannelIface)			return o;		boolean bBatchableIfaceFound = false;		try {			//first retrieve a list of implemented by 'o' interfaces			// they are received as array of Strings so we need to resove them locally first			String[] classNames = ((ChannelIface)o).getInterfaces();			ifaces = new Class[classNames.length];			for (int i = 0; i < classNames.length; i++) {				// resolve them				if (!bBatchableIfaceFound						&& (0 == Batchable.class.getName().compareTo(classNames[i])))					bBatchableIfaceFound = true;				ifaces[i] = Class.forName(classNames[i]);			}		}		catch (Exception e) {			throw new Exception("while wraping ", e);		}		// finally create a Dynamic Proxy whith those interfaces		return Proxy.newProxyInstance(				ChannelIfaceInvocation.class.getClassLoader(), ifaces,				new ChannelIfaceInvocation((ChannelIface)o, bBatchableIfaceFound));	} //wrapIt	/**	 * the only constructor	 * @param remote - an instance to which all the 'invoke's are directed	 * @param bCanBatch indicate while to suspend the method batching for that	 * particular instance. It is set to false by the presence of <code>NotBatchable</code> interface	 * into the list of implemented interfaces by the remote instance which is subject of wrapping	 */	public ChannelIfaceInvocation(ChannelIface remote, boolean bCanBatch) {		remoteInstance = remote;		this.bCanBatch = bCanBatch;	}	/**	 * a helper which sends the method invocation requests to the remote instance	 * and try to resiolve the return value to some locally stubbed object.	 * This is neccessary because we like to avoid multiple wrappings around such objects	 * @param method is the description of the method being invoked	 * @param args are the arguments passed to the method	 * @return thre value returned by the ral method	 * @throws Throwable if some exception occur. it will be wrapped into an RemoteException	 * this way, later, we'll be able to get it's 'cause' and rise it locally.	 * All this is an attempt to mimic the remote object's behaviour into the local	 * context from where the method invocaation were originated.	 */	public Object invoke(final Object method, final Object[] args)		throws Throwable	{		try {			//do the invoke			Object result = remoteInstance.invoke(method, args);			// resolve the return value to local object if possible			if (result instanceof Remote) {				ChannelIfaceImpl tryAsLocal = ChannelIfaceImpl.getRef((Remote)result);				if (tryAsLocal != null)					return tryAsLocal.instance;			}			// if can't be resoved, try to wrapit (wuill happen only for instances implementing ChannelIface			return wrapIt(result);		}		catch (RemoteException e) {			// if any exception occur remotely - access it through the 'cause of the			// RemoteException and Rise it locally			if (e.detail != null && e.detail instanceof RemoteException)				throw ((RemoteException)e.detail).detail;			else				throw e.detail;		}	} //invoke	// the batched jobs are kept here.	// all methods which returns 'void' and receive only native and Serializable arguments,	// in our opinion, can be safely batched and later, passed at once to the other side,	// without attracting the others's side processing logic. The main assumption is	// the such methods cannot manipulate the runnig context because they do cannnot change anyting	// on th eother side of the channel. Of ciource this is not true for all the use cases - especially for those	// which rely on side effects so suvch batching do not occur if the wrapped instance	// implements 'NotBatchable' itreface. on the first invocation of 'non-void' method or	// a suvch thet hase other than 'Serializable' and native araguments - the Batch Job queue is	// flushed before we made the such call to thge other side of the chanel	java.util.Vector jobs = new java.util.Vector();	/**	 * adds a job to the batch queue.	 * @param job job to add. If the passed job ref is 'null' we flush the queue	 * @throws RemoteException	 */	void addJob(Job job)		throws RemoteException	{		synchronized(jobs) {			if (job != null)				jobs.add(job);			int sz = jobs.size();			if (sz == 0)				return;			if (job == null || sz > JOB_QUEUE_SIZE) {				remoteInstance.batch(jobs.toArray());				jobs.clear();			}		}	}	/**	 * Handle instance method invocations. Here we describe th einvoked method so to be	 * uniquely indentified on th eother side. This description is constructed from	 * the name of the method being invoked followed by the names of the classes of its arguments.	 * The delimiter used to separate these values is '|' character. Once constructed it is	 * coverted to char array - to somehow reduce the net traffic a bit.	 * @param proxy - unused here because we like to invoke an remote instance's method	 * @param method - a method being invoked	 * @param args are th earguments passed for the call	 * @return is what the real method returns from the call.	 * @throws Throwable it is the exception rised wrom the other side. It is good to use	 * fully serializable exceptions because, if not, they couldn't be transported here at all.	 */	public Object invoke(Object proxy, java.lang.reflect.Method method,			Object[] args)		throws Throwable	{		// the first indication that we could batch this method call is its retun value.		boolean canBatch = bCanBatch && method.getReturnType().equals(void.class);		// get the method's declared argument types		Class[] paramTypes = method.getParameterTypes();		// construct thge description with aid of stringBuffer		StringBuffer methodDescription = new StringBuffer();		// then add its name as first token		methodDescription.append(method.getName());		// go through the passed arguments		for (int i = 0; i < paramTypes.length; i++) {			// if the current argumen isn't native or Remote or serializable			// try to create a local stp and pass this stub instead			if (null != args[i]					&& false == args[i] instanceof java.io.Serializable					&& false == args[i].getClass().isPrimitive()					&& false == args[i] instanceof Remote)			{				// if syuch an condition occur - suspend the method batching				canBatch = false;				args[i] = ChannelIfaceImpl.createStub(args[i]);			}			// if not stubbed but still Remote then aganin suspend the method batching			if (args[i] instanceof Remote) {				canBatch = false;			}			// if it is a locally wrapped proxy try to unwrap and pass the remote ref instead			if (true == (args[i] instanceof Proxy)) {				InvocationHandler oIH = Proxy.getInvocationHandler(args[i]);				if (oIH instanceof ChannelIfaceInvocation)					args[i] = ((ChannelIfaceInvocation)oIH).remoteInstance;				// this is also a condition on which we suspend method batching				canBatch = false;			}			// append the method's declared arcumet type preceded by the used delimiter			methodDescription.append('|').append(paramTypes[i].getName());		}// loop through the arguments		if (canBatch) {			// in case we still can batch the request - put it into the queue			addJob(new Job(methodDescription.toString(), args));			return null;		}		else {			// otherwise fluss it and continue with the method invocation 'as usual'			addJob(null);		}		return invoke(methodDescription.toString().toCharArray(), args);	} //InvocationHandler.invoke	/**	 * just to notify the other side when the ref is being garbage collected here	 */	protected void finalize() {		try {			remoteInstance.gotFinalized();		}		catch (RemoteException ee) {		}		remoteInstance = null;	}} // ChannelIfaceInvocation

⌨️ 快捷键说明

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