All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.taobao.api.internal.toplink.remoting.DynamicProxy Maven / Gradle / Ivy

package com.taobao.api.internal.toplink.remoting;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.URI;
import java.nio.ByteBuffer;
import java.util.HashMap;

import com.taobao.api.internal.toplink.BufferManager;
import com.taobao.api.internal.toplink.Text;
import com.taobao.api.internal.toplink.channel.ChannelException;
import com.taobao.api.internal.toplink.channel.ClientChannel;
import com.taobao.api.internal.toplink.channel.ClientChannelSelector;
import com.taobao.api.internal.toplink.channel.ChannelSender.SendHandler;
import com.taobao.api.internal.toplink.protocol.tcp.TcpOperations;
import com.taobao.api.internal.toplink.protocol.tcp.TcpTransportHeader;

public class DynamicProxy implements InvocationHandler {
	private int executionTimeout = 0;
	private URI remoteUri;
	private String uriString;
	private String serializationFormat;
	private ClientChannelSelector selector;
	private RemotingClientChannelHandler channelHandler;

	protected DynamicProxy(URI remoteUri,
			ClientChannelSelector selector,
			RemotingClientChannelHandler handler) {
		this.remoteUri = remoteUri;
		this.uriString = remoteUri != null ? remoteUri.toString() : "";
		this.selector = selector;
		this.channelHandler = handler;
	}

	public Object create(Class interfaceClass, URI remoteUri) {
		this.uriString = remoteUri.toString();
		return Proxy.newProxyInstance(
				interfaceClass.getClassLoader(),
				new Class[] { interfaceClass },
				this);
	}

	public void setExecutionTimeout(int millisecond) {
		this.executionTimeout = millisecond;
	}

	public void setSerializationFormat(String format) {
		this.serializationFormat = format;
	}

	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		MethodCall methodCall = new MethodCall();
		methodCall.Uri = this.uriString;
		methodCall.MethodName = method.getName();
		methodCall.TypeName = method.getDeclaringClass().getName();
		methodCall.MethodSignature = method.getParameterTypes();
		methodCall.Args = args;

		MethodReturn methodReturn = this.invoke(methodCall, method.getReturnType());

		if (methodReturn.Exception == null)
			return methodReturn.ReturnValue;

		// https://github.com/wsky/top-link/issues/18
		// will course java.lang.reflect.UndeclaredThrowableException
		// throw new RemotingException("invoke got error",
		// methodReturn.Exception);
		throw methodReturn.Exception;
	}

	public MethodReturn invoke(MethodCall methodCall) throws RemotingException, FormatterException {
		return this.invoke(methodCall, Object.class);
	}

	public MethodReturn invoke(MethodCall methodCall,
			Class returnType) throws RemotingException, FormatterException {
		return this.invoke(methodCall, returnType, this.executionTimeout);
	}

	public MethodReturn invoke(MethodCall methodCall,
			int executionTimeoutMillisecond) throws RemotingException, FormatterException {
		return this.invoke(methodCall, Object.class, executionTimeoutMillisecond);
	}

	public MethodReturn invoke(MethodCall methodCall,
			Class returnType,
			int executionTimeoutMillisecond) throws RemotingException, FormatterException {
		SynchronizedRemotingCallback syncCallback = new SynchronizedRemotingCallback();
		syncCallback.returnType = returnType;
		syncCallback.serializationFormat = this.serializationFormat;

		HashMap transportHeaders = new HashMap();
		transportHeaders.put(TcpTransportHeader.RequestUri, this.uriString);

		ClientChannel channel = this.getChannel();
		try {
			return this.send(channel,
					this.channelHandler.pending(syncCallback,
							TcpOperations.Request, transportHeaders, methodCall),
					syncCallback,
					executionTimeoutMillisecond);
		} finally {
			this.selector.returnChannel(channel);
		}
	}

	private ClientChannel getChannel() throws RemotingException {
		try {
			ClientChannel channel = this.selector.getChannel(this.remoteUri);
			channel.setChannelHandler(channelHandler);
			return channel;
		} catch (ChannelException e) {
			throw new RemotingException(Text.RPC_CAN_NOT_GET_CHANNEL, e);
		}
	}

	private MethodReturn send(ClientChannel clientChannel,
			final ByteBuffer buffer,
			SynchronizedRemotingCallback syncCallback,
			int executionTimeoutMillisecond) throws RemotingException {
		// reset buffer limit and position for send
		buffer.flip();

		try {
			clientChannel.send(buffer, new SendHandler() {
				public void onSendComplete(boolean success) {
					BufferManager.returnBuffer(buffer);
				}
			});
		} catch (ChannelException e) {
			throw unexcepException(syncCallback, Text.RPC_SEND_ERROR, e);
		}

		try {
			syncCallback.waitReturn(executionTimeoutMillisecond);
		} finally {
			this.channelHandler.cancel(syncCallback);
		}

		if (syncCallback.getFailure() != null)
			throw unexcepException(
					syncCallback, 
					Text.RPC_CALL_ERROR, 
					syncCallback.getFailure());

		return syncCallback.getMethodReturn();
	}

	private RemotingException unexcepException(
			SynchronizedRemotingCallback callback, String message, Throwable innerException) {
		if (innerException instanceof RemotingException)
			return (RemotingException) innerException;
		return innerException != null
				? new RemotingException(message, innerException)
				: new RemotingException(message);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy