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

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

The newest version!
package com.taobao.api.internal.toplink.remoting;

import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

import com.taobao.api.internal.toplink.BufferManager;
import com.taobao.api.internal.toplink.Logger;
import com.taobao.api.internal.toplink.LoggerFactory;
import com.taobao.api.internal.toplink.Text;
import com.taobao.api.internal.toplink.channel.ChannelContext;
import com.taobao.api.internal.toplink.channel.SimpleChannelHandler;
import com.taobao.api.internal.toplink.protocol.NotSupportedException;
import com.taobao.api.internal.toplink.protocol.tcp.TcpContentDelimiter;
import com.taobao.api.internal.toplink.protocol.tcp.TcpOperations;
import com.taobao.api.internal.toplink.protocol.tcp.TcpTransportHeader;
import com.taobao.api.internal.toplink.remoting.protocol.RemotingTcpProtocolHandle;
import com.taobao.api.internal.toplink.remoting.protocol.RemotingTransportHeader;

public class RemotingClientChannelHandler extends SimpleChannelHandler {
	private Logger logger;
	private AtomicInteger flagAtomic;
	private Map callbacks;
	private SerializationFactory serializationFactory;

	public RemotingClientChannelHandler(LoggerFactory loggerFactory, AtomicInteger flagAtomic) {
		this.logger = loggerFactory.create(this);
		this.flagAtomic = flagAtomic;
		this.callbacks = new ConcurrentHashMap();
		this.serializationFactory = new DefaultSerializationFactory();
	}

	public void setSerializationFactory(SerializationFactory serializationFactory) {
		this.serializationFactory = serializationFactory;
	}

	public ByteBuffer pending(RemotingCallback handler,
			short operation,
			HashMap transportHeaders,
			MethodCall methodCall)
			throws FormatterException {
		byte[] data = this.serializationFactory.
				get(handler.serializationFormat).
				serializeMethodCall(methodCall);
		return this.pending(handler,
				operation,
				transportHeaders,
				data,
				0,
				data.length);
	}

	// act as formatter sink
	public ByteBuffer pending(RemotingCallback handler,
			short operation,
			HashMap transportHeaders,
			byte[] data,
			int dataOffset,
			int dataLength) {
		Integer flag = this.flagAtomic.incrementAndGet();

		ByteBuffer requestBuffer = BufferManager.getBuffer();
		RemotingTcpProtocolHandle handle = new RemotingTcpProtocolHandle(requestBuffer);
		handle.WritePreamble();
		handle.WriteMajorVersion();
		handle.WriteMinorVersion();
		handle.WriteOperation(TcpOperations.Request);
		handle.WriteContentDelimiter(TcpContentDelimiter.ContentLength);
		handle.WriteContentLength(data.length);
		transportHeaders.put(RemotingTransportHeader.Flag, flag);
		transportHeaders.put(RemotingTransportHeader.Format, handler.serializationFormat);
		handle.WriteTransportHeaders(transportHeaders);
		handle.WriteContent(data);

		handler.flag = flag;
		this.callbacks.put(handler.flag, handler);
		if (this.logger.isDebugEnabled())
			this.logger.debug(Text.RPC_PENDING_CALL, flag);

		return requestBuffer;
	}

	public void cancel(RemotingCallback callback) {
		this.callbacks.remove(callback.flag);
	}

	public void onMessage(ChannelContext context) {
		Object msg = context.getMessage();
		RemotingTcpProtocolHandle protocol = msg instanceof ByteBuffer ?
				new RemotingTcpProtocolHandle((ByteBuffer) msg) :
				(RemotingTcpProtocolHandle) msg;
		protocol.ReadPreamble();
		protocol.ReadMajorVersion();
		protocol.ReadMinorVersion();

		short operation = protocol.ReadOperation();
		if (operation != TcpOperations.Reply)
			return;

		protocol.ReadContentDelimiter();
		protocol.ReadContentLength();

		HashMap transportHeaders = null;
		try {
			transportHeaders = protocol.ReadTransportHeaders();
		} catch (NotSupportedException e) {
			this.logger.error(e);
		}
		Object flag;
		if (transportHeaders == null ||
				(flag = transportHeaders.get(RemotingTransportHeader.Flag)) == null)
			return;

		if (this.logger.isDebugEnabled())
			this.logger.debug(Text.RPC_GET_RETURN, flag);

		RemotingCallback callback = this.callbacks.remove(flag);
		if (callback == null)
			return;

		Object statusCode = transportHeaders.get(TcpTransportHeader.StatusCode);
		Object statusPhrase = transportHeaders.get(TcpTransportHeader.StatusPhrase);
		if (statusCode != null &&
				Integer.parseInt(statusCode.toString()) > 0) {
			callback.onException(new Exception(String.format(
					Text.RPC_RETURN_ERROR, statusCode, statusPhrase)));
			return;
		}

		MethodReturn methodReturn = null;
		try {
			methodReturn = this.serializationFactory.
					get(callback.serializationFormat).
					deserializeMethodReturn(protocol.ReadContent(), callback.returnType);
		} catch (FormatterException e) {
			callback.onException(e);
			return;
		}

		try {
			callback.onMethodReturn(methodReturn);
		} catch (Exception e) {
			this.logger.error(e);
		}
	}

	@Override
	public void onClosed(String reason) {
		RemotingException error = new RemotingException(Text.RPC_CHANNEL_BROKEN);
		// all is fail!
		for (Entry i : this.callbacks.entrySet()) {
			try {
				i.getValue().onException(error);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		this.callbacks = new HashMap();
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy