net.hasor.rsf.protocol.hprose.HproseUtils.java Source code

Java tutorial

Introduction

Here is the source code for net.hasor.rsf.protocol.hprose.HproseUtils.java

Source

/*
 * Copyright 2008-2009 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.hasor.rsf.protocol.hprose;

import io.netty.buffer.ByteBuf;
import net.hasor.core.utils.StringUtils;
import net.hasor.libs.com.hprose.io.HproseReader;
import net.hasor.libs.com.hprose.io.HproseTags;
import net.hasor.libs.com.hprose.io.HproseWriter;
import net.hasor.rsf.RsfBindInfo;
import net.hasor.rsf.RsfContext;
import net.hasor.rsf.domain.*;
import net.hasor.rsf.json.JSON;
import net.hasor.rsf.utils.ProtocolUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.*;

import static io.netty.handler.codec.http.HttpHeaders.Names.LOCATION;
import static io.netty.handler.codec.http.HttpHeaders.Names.ORIGIN;

/**
 * Hprose 
 * @version : 2017128
 * @author (zyc@hasor.net)
 */
public class HproseUtils implements HproseConstants {
    public static final String HPROSE = "Hprose";

    /***/
    public static RequestInfo[] doCall(RsfContext rsfContext, ByteBuf content, String requestURI, String origin)
            throws RsfException {
        //
        HproseReader reader = new HproseReader(content.nioBuffer());
        List<RequestInfo> infoArrays = new ArrayList<RequestInfo>();
        //
        parseRequest(rsfContext, reader, infoArrays);
        content.skipBytes(content.readableBytes());
        //
        for (RequestInfo info : infoArrays) {
            info.addOption(LOCATION, requestURI);
            info.addOption(ORIGIN, origin);
        }
        //
        return infoArrays.toArray(new RequestInfo[infoArrays.size()]);
    }

    /***/
    private static void parseRequest(RsfContext rsfContext, HproseReader reader, List<RequestInfo> infoArrays) {
        long requestID = 12345;
        String callName = null;
        try {
            callName = reader.readString();
            reader.reset();
        } catch (IOException e) {
            throw new RsfException(ProtocolStatus.ProtocolError, "decode callName error -> " + e.getMessage());
        }
        //
        //  RequestInfo 
        RsfBindInfo<?> serviceInfo = null;
        RequestInfo request = new RequestInfo();
        request.setRequestID(requestID);
        try {
            String[] lastParams = callName.split("_");
            String methodName = lastParams[lastParams.length - 1];
            String serviceID = callName.substring(0, callName.length() - methodName.length() - 1);
            //
            serviceInfo = rsfContext.getServiceInfo(HPROSE, serviceID);
            if (serviceInfo == null) {
                throw new RsfException(ProtocolStatus.NotFound, "serviceID not found in alias. -> " + serviceID);
            }
            //
            request.setServiceGroup(serviceInfo.getBindGroup());
            request.setServiceName(serviceInfo.getBindName());
            request.setServiceVersion(serviceInfo.getBindVersion());
            request.setTargetMethod(methodName);
            request.setMessage(false);
            request.setSerializeType("Hprose");
            request.setClientTimeout(rsfContext.getSettings().getDefaultTimeout());
            request.setReceiveTime(System.currentTimeMillis());
        } catch (Exception e) {
            if (e instanceof RsfException)
                throw (RsfException) e;
            throw new RsfException(ProtocolStatus.Unknown, "error(" + e.getClass() + ") -> " + e.getMessage());
        }
        // 
        int lastTag = 0;
        Method atMethod = null;
        Class<?>[] parameterTypes = null;
        byte[][] args = null;
        try {
            int argCount = 0;
            String methodName = request.getTargetMethod();
            lastTag = reader.checkTags(new StringBuilder().append((char) TagList).append((char) TagEnd)
                    .append((char) TagCall).toString());
            if (lastTag == HproseTags.TagList) {
                reader.reset();
                argCount = reader.readInt(HproseTags.TagOpenbrace);
                args = new byte[argCount][];
                for (int i = 0; i < argCount; i++) {
                    ByteArrayOutputStream out = new ByteArrayOutputStream();
                    reader.readRaw(out);
                    args[i] = out.toByteArray();
                }
                reader.readInt(HproseTags.TagClosebrace);
            }
            args = (args == null) ? new byte[0][] : args;
            Method[] allMethods = serviceInfo.getBindType().getMethods();
            for (Method method : allMethods) {
                if (!method.getName().equals(methodName))
                    continue;
                parameterTypes = method.getParameterTypes();
                if (argCount != parameterTypes.length)
                    continue;
                atMethod = method;
                break;
            }
            if (atMethod == null) {
                throw new RsfException(ProtocolStatus.NotFound,
                        "serviceID : " + serviceInfo.getBindID() + " ,not found method " + methodName);
            }
            //
        } catch (Exception e) {
            if (e instanceof RsfException)
                throw (RsfException) e;
            throw new RsfException(ProtocolStatus.Unknown, "error(" + e.getClass() + ") -> " + e.getMessage());
        }
        // .??(isRef?? (??response??)
        for (int i = 0; i < parameterTypes.length; i++) {
            Class<?> paramType = parameterTypes[i];
            byte[] paramBytes = args[i];
            //Object paramData = (args.length >= i) ? args[i] : null;
            String typeByte = RsfRuntimeUtils.toAsmType(paramType);
            request.addParameter(typeByte, paramBytes, null);
        }
        // .?
        infoArrays.add(request);
        //
        // .???????
        try {
            if (lastTag == TagEnd)
                return;
            lastTag = reader.checkTags(new StringBuilder().append((char) TagTrue).append((char) TagEnd)
                    .append((char) TagCall).toString());
        } catch (Exception e) {
            if (e instanceof RsfException)
                throw (RsfException) e;
            throw new RsfException(ProtocolStatus.SerializeError,
                    "error(" + e.getClass() + ") reader.checkTags -> " + e.getMessage());
        }
        //
        // .???????
        if (lastTag == TagEnd) {
            return;
        }
        // .call??
        if (lastTag == TagCall) {
            throw new RsfException(ProtocolStatus.ProtocolError, "hprose batch calls, is not support.");
            //parseRequest(rsfContext, reader, infoArrays);
        }
        // .????????
        if (lastTag == TagTrue) {
            throw new RsfException(ProtocolStatus.ProtocolError, "hprose ref param, is not support.");
        }
    }

    /***/
    public static ByteBuf doResult(long requestID, ResponseInfo response) {
        ByteBuf outBuf = ProtocolUtils.newByteBuf();
        if (response.getStatus() == ProtocolStatus.OK) {
            outBuf.writeByte((byte) 'R');
            outBuf.writeBytes(response.getReturnData());
            outBuf.writeByte((byte) 'z');
            //
        } else {
            Map<String, String> errorMsg = new HashMap<String, String>();
            String[] optionKeys = response.getOptionKeys();
            if (optionKeys != null) {
                for (String optKey : optionKeys) {
                    errorMsg.put(optKey, response.getOption(optKey));
                }
            }
            errorMsg.put("requestID", String.valueOf(requestID));
            errorMsg.put("status", String.valueOf(response.getStatus()));
            String jsonData = JSON.toString(errorMsg);
            String data = "s" + jsonData.length() + "\"" + jsonData + "\"z";
            //
            outBuf.writeByte((byte) 'E');
            outBuf.writeBytes(data.getBytes());
        }
        return outBuf;
    }

    //
    public static ByteBuf doFunction(RsfContext rsfContext) throws IOException {
        Set<String> allMethod = new LinkedHashSet<String>();
        allMethod.add("*");
        //
        // .
        List<String> serviceIDs = rsfContext.getServiceIDs();
        for (String serviceID : serviceIDs) {
            RsfBindInfo<?> serviceInfo = rsfContext.getServiceInfo(serviceID);
            if (serviceInfo.isShadow() || RsfServiceType.Provider != serviceInfo.getServiceType())
                continue;
            String aliasName = serviceInfo.getAliasName(HPROSE);
            if (StringUtils.isBlank(aliasName)) {
                continue;
            }
            //
            Method[] methodArrays = serviceInfo.getBindType().getMethods();
            for (Method method : methodArrays) {
                StringBuilder define = new StringBuilder();
                define = define.append(aliasName);
                define = define.append("_");
                define = define.append(method.getName());
                allMethod.add(define.toString());
            }
            //
        }
        //
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        HproseWriter writer = new HproseWriter(out);
        String[] array = allMethod.toArray(new String[allMethod.size()]);
        writer.writeArray(array);
        //
        ByteBuf outBuf = ProtocolUtils.newByteBuf();
        outBuf.writeByte('F');
        outBuf.writeBytes(out.toByteArray());
        outBuf.writeByte('z');
        return outBuf;
    }
}